前言
上一篇 Spring 事件机制概述 的文章中,从观察者模式、Java 事件机制、Spring 事件机制的具体代码实现进行了简要的分析。本篇文章将在其基础上对 Spring 事件机制的源码进行分析。
- Spring 事件机制流程回顾
- 创建一个具体的事件类,该类需继承 ApplicationEvent;
- 创建一个针对某个特定时间的监听器实现 ApplicationListener,并配置 @Component 注解,确保 Ioc 容器启动时,监听器会注入至 Ioc 容器;
- 初始化 Ioc 容器;
- 由于 ApplicationContext 实现了 ApplicationEventPublisher,因此直接使用 ApplicationContext 作为事件发布器发布某个事件,此时该事件的监听器便会接收到事件并做出相应的处理。此处也可以通过实现 ApplicationEventPublisherAware 接口,来获得事件发布器。
上述的流程中,可能会有这样一些疑问:
- 事件监听器是何时被注入的?
- 事件发布器是怎么样对具体的事件进行发布?
带着这两个疑问,开始源码的分析。
Spring 事件机制源码分析
在实际应用的代码中,Ioc 容器 ApplicationContext 创建完成后,监听器 ApplicationListener 及发布器 ApplicationEventPublisher 均已就绪,可直接使用进行事件发布,故从 ApplicationContext 初始化着手来分析。 通过对 Spring Ioc 的源码分析,我们知道了容器初始化的核心方法为 AbstractApplicationContext::refresh,查看 refresh 方法,我们发现有两个方法与 Spring 的事件相关。
-
initApplicationEventMulticaster 方法
-
ApplicationEventMulticaster(事件多播器)
ApplicationEventMulticaster 接口的方法主要是操作 ApplicationListener, 广播 ApplicationEventpublic interface ApplicationEventMulticaster { void addApplicationListener(ApplicationListener<?> listener); void addApplicationListenerBean(String listenerBeanName); void removeApplicationListener(ApplicationListener<?> listener); void removeApplicationListenerBean(String listenerBeanName); void removeAllListeners(); void multicastEvent(ApplicationEvent event); void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType); }
分析其继承关系,在抽象类 AbstractApplicationEventMulticaster 中实现了接口的方法,SimpleApplicationEventMulticaster 中引入异步操作的支持。相关源码会在后面串联分析。
-
源码
源码的核心流程是,先判断 BeanFactory 中有没有 ApplicationEventMulticaster 类,若有则赋值给本地变量,若无则创建 SimpleApplicationEventMulticaster 并赋值给本地变量。protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }
-
-
registerListeners
- 源码分析
从 registerListeners 源码中可以看到,该方法中只是将 ApplicationListener 对应的 BeanName 保存起来了,因此这个时候 Bean 都还没有完成初始化,只有 beanDefinition 的信息,后续在完成 Bean 初始化后,会调用一个后置处理器 ApplicationListenerDetector 的 postProcessAfterInitialization 方法,将 ApplicationListener 对应的 Bean 实例绑定到 ApplicationEventMulticaster 中。
protected void registerListeners() { // Register statically specified listeners first. // getApplicationListeners 方法中返回本地的 applicationListeners for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! // 从 BeanFactory 中找到 ApplicationListener 类所对应的所有 BeanName String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
- 源码分析
在完成 ApplicationEventMulticaster 初始化,监听器注入后,后续就是如何发布事件,从 ApplicationContext 的类继承关系中知道,该类继承了 ApplicationEventPublisher,在 AbstractApplicationContext 类中实现了方法 publishEvent,具体源码为:
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 使用事件广播器广播该事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// getApplicationListeners 根据 event 的类型找到相应的 listener
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 增加了对异步事件的支持,如果 executor 不为空则异步通知该事件
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
总结
从上述的分析中可知,Spring 事件发布的主要流程为:
- 初始化 事件多播器(ApplicationEventMulticaster)
- 注册 ApplicationListener
- 调用后置处理器 ApplicationListenerDetector 完成 ApplicationEventMulticaster 中 listener 实例的赋值;
- 发布事件时,调用 ApplicationEventMulticaster 的广播方法,将 Event 广播至对应的 Listener。
Spring 提供了以下 5 中标准的事件,我们可以注册响应的监听器进行处理该事件。
- 上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。