- Spring 监听器listener原理-基本使用(一)
- Spring 监听器listener原理-手写监听器(二)
- Spring 监听器listener原理-spring监听器源码分析(三)
文章目录
概述
要理解ApplicationListener的实现原理,需要对Spring的扩展点BeanPostProcessor
有一点了解。这个接口是Spring最重要的接口之一,这个接口与Spring Bean的生命周期息息相关,我们常说的实例化前,实例化后,属性注入,初始化前,初始化后等等,其实都是调用了BeanPostProcessor
或它子类的方法。有关于BeanPostProcessor
的简单介绍可以参考文章,spring也是借助于bean的后置处理器查找实现了ApplicationListener的监听器
前面两篇文章中,我们可以总结事件发布大概有如下组件
- 事件广播器,可以理解是我们的
applicationContext
。 - 事件
ApplicationEvent
。 - 事件监听器
ApplicationListener
。
那么Spring是如何找到所有的ApplicationListener以及是如何判断是否是当前监听器感兴趣的事件的,下面将为大家解答。
事件发布者
当Spring容器启动的时候会调用refresh初始化容器
org.springframework.context.support.AbstractApplicationContext#refresh
在refresh会调用initApplicationEventMulticaster进行事件广播器的初始化
@Override
public void refresh() throws BeansException, IllegalStateException {
.........省略
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
.........省略
}
下面代码的逻辑最要是判断容器中是否有名字叫applicationEventMulticaster
的事件广播器,如果有则使用已有的(这也算是Spring的一个扩展点,也就是或如果我们创建了个名字是applicationEventMulticaster
的事件广播器,那么就会使用我们自定义的),如果没有则新建默认的事件广播器SimpleApplicationEventMulticaster
。这里会赋值给applicationEventMulticaster
成员变量。applicationContext
也实现了ApplicationEventPublisher
接口,所以它拥有事件相关的所有方法,但applicationContext
只是一个代理,当我们调用applicationContext.publishEvent
方法时,其实调用的就是applicationEventMulticaster
这个成员变量对象。
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//首先看spring容器中是不是已经有名字为applicationEventMulticaster的对象,
//如果有这使用容器中已有的对象并赋值给applicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
//如果没有则新建一个SimpleApplicationEventMulticaster对象,并赋值给applicationEventMulticaster ;
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
事件发布
事件发布的关键方法流程如下
org.springframework.context.support.AbstractApplicationContext#publishEvent
-->org.springframework.context.support.AbstractApplicationContext#publishEvent
-->org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent //发布事件
-->org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners //找到感兴趣的事件
-->org.springframework.context.event.AbstractApplicationEventMulticaster#retrieveApplicationListeners//找到感兴趣的事件
-->org.springframework.context.event.AbstractApplicationEventMulticaster#supportsEvent //判断是否是感兴趣的事件
multicastEvent
multicastEvent
方法很简单,调用getApplicationListeners
方法找到所有对当前事件感兴趣的监听器,如果存在线程池,则异步执行监听逻辑,否则同步执行。默认情况下执行事件的逻辑是跟发布事件是同一个线程
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
//getApplicationListeners 方法找到所有的对当前事件感兴趣的监听器
for (ApplicationListener<?> listener :