Spring的事件包含三部分
- 事件(ApplicationEvent):继承自 jdk 的 EventObject,所有的事件都需要继承 ApplicationEvent,并且通过构造器参数 source 得到事件源.
- 应用事件监听器(ApplicationListener):继承自 jdk 的 EventListener,所有的监听器都要实现这个接口
- 事件发布者(ApplicationEventPublisher,ApplicationContext 实现了 ApplicationEventPublisher 接口):具体实现类是 SimpleApplicationEventMulticaster,在 Spring 中维护监听者。
ApplicationEventMulticaster#multicastEvent
方法将事件传给监听器
Spring默认事件类型
- ContextRefreshedEvent:在初始化或刷新时 ApplicationContext 发布
- ContextStartedEvent:通过在 ConfigurableApplicationContext 接口上使用 start() 方法启动 ApplicationContext 时发布,通常,此信号用于在显式停止后重新启动 bean
- ContextStoppedEvent:使用 ConfigurableApplicationContext 接口上的 stop()方法停止 ApplicationContext 时发布,停止的上下文可以通过 start() 调用重新启动
- ContextClosedEvent:通过使用 ConfigurableApplicationContext 接口上的 close() 方法或通过 JVM shutdown hook钩子函数在 ApplicationContext 被关闭时发布。在这里,“关闭”意味着所有单例 bean 都将被销毁
- RequestHandledEvent:一个特定于 web 的事件,它告诉所有 bean 一个 HTTP 请求已经得到了服务。此事件在请求完成后发布。此事件仅适用于使用 Spring 的 DispatcherServlet 的 Web 应用程序
自定义事件
注解方式
新建一个用户注册事件,继承ApplicationEvent
public class UserRegisterEvent extends ApplicationEvent {
public UserRegisterEvent(User user) {
super(user);
}
}
创建两个事件监听器,@EventListener
注解用在方法上
@Slf4j
@Service
public class UserRegisterListener {
@EventListener
public void sendMsg(UserRegisterEvent userRegisterEvent) {
User user = (User) userRegisterEvent.getSource();
log.info("发送短信,手机号{}", user.getPhone());
}
@EventListener
public void sendEmail(UserRegisterEvent userRegisterEvent) {
User user = (User) userRegisterEvent.getSource();
log.info("发送邮箱,邮箱{}", user.getEmail());
}
}
在用户注册逻辑完成后,发布用户注册事件
@Service
public class UserServiceImpl {
public final ApplicationEventPublisher applicationEventPublisher;
public UserServiceImpl(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void register() {
log.info("用户注册");
// 发送用户注册事件
applicationEventPublisher.publishEvent(new UserRegisterEvent(User.builder().name("lisi").email("abc@xxx.com").phone("8008208820").build()));
}
}
运行结果:
可以看到事件已经发布,并且监听成功。
但是从图上可以看到,主逻辑和监听事件的线程是同一个,也就是在同一个线程中执行,如果想多线程做异步处理,该怎么做?