Spring事件体系包括三个组件:事件、发布器、监听器。事件是主体,发布器负责发布事件,监听器负责处理事件。Spring事件使用的是监听者模式,他的优点在于低耦合、侵入性相对较小。
下面介绍下Spring事件如何使用。
自定义事件需要继承ApplicationEvent。Spring里面也内置了很多事件也都是基于继承ApplicationEvent类
下面我们自己定义一个事件,该事件主要处理订单对象Order
/**
* 定义订单事件
* @author jiangleilei
* @date 2023/10/10 09:34
*/
public class OrderEvent extends ApplicationEvent {
private Order order;
public OrderEvent(Object source, Order order) {
super(source);
this.order = order;
}
}
事件监听器需要实现ApplicationListener接口,一个事件可以有多个监听者,当时间发布时,所有该事件的监听者都可以收到监听通知。
/**
* 事件监听器,专监听OrderEvent事件
* @author jiangleilei
* @date 2023/10/10 09:36
*/
@Component //监听器需要交给Spring管理,至于为什么下文会有提到
public class OrderEventListener implements ApplicationListener<OrderEvent> {
//event = 事件对象
@Override
public void onApplicationEvent(OrderEvent event) {
//通过事件对象,我们可以拿到事件里面的任何属性,如果需要更多信息,我们也可以在事件里面定义更多属性
Order order = event.getOrder();
System.out.println("收到监听事件1");
}
}
//将ApplicationContext注入到类里面去
@Autowired
private ApplicationContext applicationContext;
public void xxx{
//创建事件,第一个参数传什么都不重要,但就是不能为null
OrderEvent order = new OrderEvent(this, new Order());
//发布事件
applicationContext.publishEvent(order);
}
在spring启动刷新的时候,会有一个准备工作也就是prepareBeanFactory方法,里面会添加BeanPostProcessor,也就是ApplicationListenerDetector后置处理器,所有的后置处理器基本上都是在实例化某些Bean的时候,对Bean做一些特殊处理,必须这个是否给这个Bean生成代理等等。。
prepareBeanFactory(beanFactory);
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
....
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
....
}
ApplicationListenerDetector属于BeanPostProcessor类型,所以任何bean的实例化,包括spring自带的bean,都要通过doGetBean创建bean实例,那么就会走到后置处理的回调方法中
ApplicationListenerDetector:主要作用:
- 在任何Bean初始化完成之后:如果Bean是单例的并且bean是ApplicationListener类型,则加入到this.applicationListeners中,applicationListeners会在广播通知的时候,会遍历监听者发送通知
- 在任何Bean销毁之前: 如果Bean是ApplicationListener类型,则会从ApplicationEventMulticaster(事件广播器)中删除。
比如上面自定义的监听者OrderEventListener就会被加到applicationListeners里面去
下面是部分源码:
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
//初始化之前
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {//判断bean是否ApplicationListener类型
Boolean flag = this.singletonNames.get(beanName);//判断是否是单利
if (Boolean.TRUE.equals(flag)) {
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
.....
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
//销毁之前
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
}
}
}
}
//添加到applicationListeners事件监听器集合里面去
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
...
this.applicationListeners.add(listener);
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
//1、线程池处理
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor(); //如果有指定线程池,那就通过指定线程池里面的线程来调用监听器,处理事件。
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { //getApplicationListeners拿到指定类型事件的监听器
//否则通过当前线程调用监听器。最终都是调用下面的invokeListener方法。
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}else {
invokeListener(listener, event);
}
}
}
//2、异常处理
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler(); //判断是否有处理发布异常的Handler
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
//3、通过我们自定义的监听器,触发重写的onApplicationEvent方法
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
listener.onApplicationEvent(event);
}
}