spring源码事件监听
spring的事件监听机制,主要利用了监听者设计模式,那如何spring自带的事件和自定义的事件是如何触发监听器的,通过源码分析
最主要的对象是事件多播器AbstractApplicationEventMulticaster,默认的情况下使用的是SimpleApplicationEventMulticaster
1.多播器的初始化
org.springframework.context.support.AbstractApplicationContext的refresh方法是spring最重要的方法,其中的两个方法处理多播器
// Initialize event multicaster for this context. 初始化multicaster
initApplicationEventMulticaster();
// Check for listener beans and register them. 注册监听
registerListeners();
(1)initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//判断beanFactory里是否定义了bean名称为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 {
//赋值applicationEventMulticaster 后续触发的时候会使用,初始化SimpleApplicationEventMulticaster的多播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//将SimpleApplicationEventMulticaster实例放到ioc容器中
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() + "]");
}
}
}
在没有自定义多播器的情况下,将SimpleApplicationEventMulticaster放到ioc容器中
(2)registerListeners 注册监听器
protected void registerListeners() {
//注册系统的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//从容器中获取监听器监听器,这里就包含了自定义的监听器,也包含了springboot监听和第三方的监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
//收集的监听器都存放defaultRetriever成员遍历里
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
首先收集spring自带的监听,在收集第三方的监听器,这里包含了自定义,springboot和第三方组件的监听器,这里要注意的是listenerBeanNames 只是获取了bean的名称,并不会初始化bean,在后续的finishBeanFactoryInitialization方法初始化bean
2.收集监听器
上面只是说到了把监听器的名称收集起来,后续监听器的执行是需要监听实例执行的
finishBeanFactoryInitialization是如何收集监听器实例的
ApplicationListenerDetector实现了bean的后置处理器BeanPostProcessor
postProcessAfterInitialization方法
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
//bean是否实现了ApplicationListener接口
if (bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
//关注postProcessMergedBeanDefinition方法中singletonNames如何赋值
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
//将bean收集起来
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
"but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed " +
"to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
Assert.notNull(listener, "ApplicationListener must not be null");
if (this.applicationEventMulticaster != null) {
//放到多播器中
this.applicationEventMulticaster.addApplicationListener(listener);
}
//放到applicationListeners
this.applicationListeners.add(listener);
}
3.事件的执行
调用publishEvent方法,这里只关注主分支,调用multicastEvent方法
@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)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
自定义事件调用的时候都是使用
applicationContext.publishEvent(event); applicationContext可以从容器中获取
4.各个事件执行时机
(1)上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
(2)上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
(3)上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
(4)上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
(5)请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。