Springboot中监听器属于事件发布机制范畴,其中角色包含:发布者、事件、监听者。
- 监听器Listener:SpringApplicationRunListener & ApplicationListener。用于处理发布者发布的事件。
- 发布者:ApplicationEventPublisher & ApplicationEventMulticaster。
- 事件:ApplicationEvent。
监听器贯穿在Springboot框架整个生命周期内:
- 阶段1:容器刷新之前。
- 阶段2:容器刷新完毕之前的监听机制。
- 阶段3:容器刷新完毕之后的监听机制
1.不同阶段的监听器
public abstract class AbstractApplicationContext{
@Override
public void refresh() throws BeansException, IllegalStateException {
...
// 阶段二
initApplicationEventMulticaster();
// 阶段二:主要初始化 WebServer
onRefresh();
// 阶段二:earlyApplicationEvents类型的事件
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 阶段三
finishRefresh();
}
}
1.1.阶段1之SpringApplicationRunListener
EventPublishingRunListener作为该监听器唯一的实现类是通过SPI机制从META-INF/spring.factories文件中加载得到的。
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
// ApplicationEventMulticaster 类型的发布器
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
}
}
该监听器贯穿在SpringBoot应用启动过程中不同的阶段,每个阶段会触发不同的ApplicationEvent。例如:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent等。
严格意义来说当前Listener并非是真正的监听器,因为其并非处理ApplicationEvent,反而是借助发布者ApplicationEventMulticaster发布上述不同阶段的事件,从这个意义来说更适合将其归类为顶级发布者Publisher。
1.2.阶段2之earlyApplicationEvents
该阶段是为应用上下文ApplicationContext初始化ApplicationEventMulticaster类型的发布者,区别于阶段1之SpringApplicationRunListener内部的发布者ApplicationEventMulticaster。
public abstract class AbstractApplicationContext{
// 此时该集合属性中的ApplicationListener 为 SPI机制获取的监听器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
private ApplicationEventMulticaster applicationEventMulticaster;
private Set<ApplicationEvent> earlyApplicationEvents;
protected void registerListeners() {
// 将已知的监听器添加到ApplicationContext中的发布者 ApplicationEventMulticaster
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 从即将被IOC容器托管的众多类中获取 ApplicationListener类型的BeanNames ~ 注意此时尚未初始化ioc容器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 如果集合earlyApplicationEvents存在ApplicationEvent元素
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
//利用 ApplicationContext中ApplicationEventMulticaster持有的全部监听器尝试发送集合earlyEventsToProcess中全部事件
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
public Collection<ApplicationListener<?>> getApplicationListeners() {
return this.applicationListeners;
}
}
从上述伪代码分析得知:该阶段的监听器完全作用于应用上下文ApplicationContext。
ApplicationContext也是ApplicationEventPublisher类型的发布者。集合earlyApplicationEvents中的元素必须ApplicationContext发布的事件,否则事件是不会被添加到earlyApplicationEvents中
在该阶段之前任何时候由发布者ApplicationContext发布的所有事件都被作为集合earlyApplicationEvents中的元素,并在此时由ApplicationContext持有的applicationEventMulticaster来触发全部的监听器处理集合earlyApplicationEvents中全部事件。
1.3.阶段3
该阶段的事件即为容器刷新完毕之后发生的事件。
public abstract class AbstractApplicationContext{
protected void finishRefresh() {
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
...
}
}
其中,Lifecycle内部会触发ServletWebServerInitializedEvent类型的事件。
2.ApplicationListener
该类型的监听器获取存在两种形式:spring.factories文件 & 监听器Listener以bean形式被ioc容器管理并获取。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
如上所示监听器处理 ApplicationEvent 的核心方法。
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
}
如果使用方直接实现接口ApplicationListener,则意味着需要处理所有的ApplicationEvent,包含框架自身出发的事件以及用户自定义Publisher触发的事件。
通常自定义的监听器直接实现SmartApplicationListener or GenericApplicationListener接口,好处是可以根据ApplicationEvent类型 or source类型过滤掉非关注的事件。
2.发布者
2.1.ApplicationEventPublisher
以ApplicationEventPublisherAware为例:
这种Aware类型的接口是被ApplicationContextAwareProcessor后置处理器触发回调的。
public interface ApplicationEventPublisherAware extends Aware {
void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}
注意此时发布者applicationEventPublisher类型为 ApplicationContext。
public abstract class AbstractApplicationContext{
private Set<ApplicationEvent> earlyApplicationEvents;
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}else {
...
}
//此时由于处于 所有bean实例化、初始化阶段,此时属性 earlyApplicationEvents 被提前置为空
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}else {
// ApplicationEventPublisherAware 触发的事件,由关注 事件类型eventType 的监听器负责处理
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
...
}
}
用户自定义一个对eventType事件类型感兴趣的监听器ApplicationListener,并处理该事件。
2.2.ApplicationEventMulticaster
通过上述章节分析得知:该类型的Publisher只是适用于SpringApplicationRunListener、ApplicationContext内部。
当前发布者发布的事件涉及哪些监听器:
- 阶段一:META-INF/spring.factories文件中内置的ApplicationListener。
- 阶段二:除了阶段一,还包括用户自定义被IOC托管的监听器。
3.ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
}
其中,source代表用户传递的数据。