强烈建议阅读本文之前,先看 spring boot 2源码系列(一)- 系统初始化器ApplicationContextInitializer。监听器的源码跟初始化器的源码有很多相似之处,例如:加载、初始化监听器,监听器委派,监听器排序。
spring boot监听器的使用
spring boot的监听器有多种配置方式。
第一种:使用spring.factories配置
1、新建Alistener实现ApplicationListener接口
// 监听ApplicationStartedEvent事件
@Order(1)
public class Alistener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("####Alistener监听到ApplicationStartedEvent");
}
}
2、在spring.factories中添加
org.springframework.context.ApplicationListener=com.example.springbootdemo.listener.Alistener
第二种:硬编码方式
1、新建Blistener实现ApplicationListener接口
// 监听ApplicationStartedEvent事件
@Order(2)
public class Blistener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("####Blistener监听到ApplicationStartedEvent");
}
}
2、修改启动类,通过代码添加Blistener
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);
// 添加监听器
springApplication.addListeners(new Blistener());
springApplication.run(args);
}
}
第三种:在application.properties配置context.listener.classes
1、新建Clistener实现ApplicationListener接口
// 监听ApplicationStartedEvent事件
@Order(3)
public class Clistener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("####Clistener监听到ApplicationStartedEvent");
}
}
2、在application.properties中配置
context.listener.classes=com.example.springbootdemo.listener.Clistener
第四种:实现GenericApplicationListener接口
1、新建Dlistener实现GenericApplicationListener接口
/**
* GenericApplicationListener是标准ApplicationListener接口的扩展变体,
* 公开了其他元数据,例如受支持的事件和源类型。
* 从Spring Framework 4.2开始,此接口取代了基于类的SmartApplicationListener,并全面处理了通用事件类型。
*/
@Order(4)
public class Dlistener implements GenericApplicationListener {
// 此监听器支持的事件类型
@Override
public boolean supportsEventType(ResolvableType eventType) {
// 监听ApplicationStartingEvent、ApplicationStartedEvent事件
return eventType.isAssignableFrom(ApplicationStartingEvent.class)
|| eventType.isAssignableFrom(ApplicationStartedEvent.class);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("####Dlistener监听到"+event.getClass().getSimpleName());
}
}
2、在spring.factories中添加配置(注意:实现类前后以及,\之间不要有空格)。
org.springframework.context.ApplicationListener=com.example.springbootdemo.listener.Alistener,\ com.example.springbootdemo.listener.Dlistener
启动工程,控制台打印
####Dlistener监听到ApplicationStartingEvent
####Clistener监听到ApplicationStartedEvent
####Alistener监听到ApplicationStartedEvent
####Blistener监听到ApplicationStartedEvent
####Dlistener监听到ApplicationStartedEvent
源码讲解—初始化阶段
spring boot监听器初始化阶段跟系统初始化器很相似,都是在创建SpringApplication实例的时候将在spring.factories配置的监听器设置给this.listeners属性。
主要源码如下:
// 源码位置 org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 将spring.factories配置的监听器赋值给this.listeners
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
}
源码讲解—运行阶段
1、进入SpringApplication#run(java.lang.String...)源码,探究监听器的运行过程
// 仅列出主要代码
org.springframework.boot.SpringApplication#run(java.lang.String...)
// 此处打断点。获取SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
// spring application 开始启动阶段
listeners.starting();
// spring application 启动完成阶段。在这里打个断点,通过启动完成阶段的代码分析spring boot监听器源码
listeners.started(context);
// spring application 运行阶段
listeners.running(context);
// SpringApplicationRunListeners讲解
class SpringApplicationRunListeners {
/**
* SpringApplicationRunListeners 是对 SpringApplicationRunListener 的封装。
* 包含多个SpringApplicationRunListener,以便能批量执行SpringApplicationRunListener的同名方法。
* 利用List<SpringApplicationRunListener> listeners 可以方便我们拓展,自定义运行监听器。
*/
private final List<SpringApplicationRunListener> listeners;
// 省略部分代码
/**
* 循环listeners并调用SpringApplicationRunListener的started同名方法。
* this.listeners默认只包含一个SpringApplicationRunListener实现类EventPublishingRunListener
*/
void started(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.started(context);
}
}
void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
// 省略部分代码
}
SpringApplicationRunListener接口定义如下:
/**
* SpringApplicationRunListener是SpringApplication运行阶段的侦听器。
*/
public interface SpringApplicationRunListener {
/**
* 在首次启动run方法时立即调用。 可用于非常早的初始化。
*/
default void starting() {
}
/**
* 在环境准备好、ApplicationContext创建之前调用。
*/
default void environmentPrepared(ConfigurableEnvironment environment) {
}
/**
* ApplicationContext已创建并准备好,但是在加载源之前。
*/
default void contextPrepared(ConfigurableApplicationContext context) {
}
/**
* 应用程序上下文已加载,但尚未刷新。
*/
default void contextLoaded(ConfigurableApplicationContext context) {
}
/**
* 上下文已刷新,应用程序已启动,CommandLineRunners和ApplicationRunner尚未被调用。
*/
default void started(ConfigurableApplicationContext context) {
}
/**
* 在run方法完成之前,当刷新应用程序上下文并且已调用所有CommandLineRunners和ApplicationRunners
*/
default void running(ConfigurableApplicationContext context) {
}
/**
* 运行应用程序时发生故障时调用
*/
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
2、进入 listeners.started();源码中
2.1 首先进入到SpringApplicationRunListeners#started 方法
// 源码位置 org.springframework.boot.SpringApplicationRunListeners#started
void started(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
// 调用SpringApplicationRunListener实现类的同名方法
listener.started(context);
}
}
2.2 listener.started(context); 分析
listener是EventPublishingRunListener。
/**
* EventPublishingRunListener是SpringApplicationRunListener接口的默认实现,用于发布事件。
* 仅展示部分代码
*/
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
// 默认事件广播器,用于广播事件
private final SimpleApplicationEventMulticaster initialMulticaster;
@Override
public int getOrder() {
return 0;
}
// 省略部分代码
// 使用SimpleApplicationEventMulticaster#multicastEvent()广播ApplicationStartedEvent事件
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
}
3、context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context)); 源码
// 源码位置 org.springframework.context.support.AbstractApplicationContext.publishEvent(java.lang.Object, org.springframework.core.ResolvableType)
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
/**
* 主要代码:
* getApplicationEventMulticaster()返回的依旧是SimpleApplicationEventMulticaster实例
* multicastEvent(applicationEvent, eventType);广播事件
*/
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
4、SimpleApplicationEventMulticaster#multicastEvent()的作用是广播事件。
// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
// 将的应用程序事件广播给对此事件感兴趣的侦听器
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 重点代码1:根据event创建ResolvableType
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
/**
* 重点代码2:getApplicationListeners(event, type)
* 返回监听了当前event事件的监听器,不监听当前事件的监听器被排除,不会返回
* event:要广播的事件
* eventType:事件类型
*/
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 若设置了线程池,使用线程调用监听器
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
// 重点代码3:没设置线程池,使用当前线程调用监听器。默认没设置线程池
invokeListener(listener, event);
}
}
}
4.1 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); 通过event创建ResolvableType。
4.2 getApplicationListeners(event, type) 返回监听了当前event事件的监听器,不监听当前事件的监听器被排除,不会返回。这是个重点的方法。
进入getApplicationListeners(event, type)中debug,会进入到 AbstractApplicationEventMulticaster#supportsEvent() 中
// 源码位置 org.springframework.context.event.AbstractApplicationEventMulticaster#supportsEvent(org.springframework.context.ApplicationListener<?>, org.springframework.core.ResolvableType, java.lang.Class<?>)
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
// 如果监听器是GenericApplicationListener的实现类则返回监听器本身,否则创建GenericApplicationListenerAdapter
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
/**
* 通过supportsEventType和supportsSourceType判断监听器是否监听了当前事件
* supportsSourceType默认返回true
*/
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
我们自己创建的Dlistener实现GenericApplicationListener接口,并重写了supportsEventType()方法,监听ApplicationStartingEvent、ApplicationStartedEvent事件。
Alistener、Blistener没实现GenericApplicationListener。与系统初始化器一样,Clistener由DelegatingApplicationListener调用,DelegatingApplicationListener也没实现GenericApplicationListener。因此会创建GenericApplicationListenerAdapter实例,再执行 (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); 判断
4.2.1 new GenericApplicationListenerAdapter(listener)); 源码分析
// 源码位置 org.springframework.context.event.GenericApplicationListenerAdapter#GenericApplicationListenerAdapter
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
// 将监听器赋值给delegate属性
this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
/**
* 获取监听器监听的事件类型。
* 例如:this.delegate = Alistener
* this.declaredEventType就等于ApplicationStartedEvent
*/
this.declaredEventType = resolveDeclaredEventType(this.delegate);
}
4.2.2 GenericApplicationListenerAdapter#supportsEventType()源码分析
// 源码位置 org.springframework.context.event.GenericApplicationListenerAdapter.supportsEventType(org.springframework.core.ResolvableType)
@Override
@SuppressWarnings("unchecked")
public boolean supportsEventType(ResolvableType eventType) {
if (this.delegate instanceof SmartApplicationListener) {
Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
}
else {
/**
* 主要代码是 this.declaredEventType.isAssignableFrom(eventType))
* 当监听器是Alistener、Blistener时:
* this.declaredEventType是ApplicationStartedEvent,eventType也是ApplicationStartedEvent,返回true
* 当监听器是DelegatingApplicationListener时:
* this.declaredEventType是ApplicationEvent,eventType是ApplicationStartedEvent,
* ApplicationEvent是ApplicationStartedEvent的父类,this.declaredEventType.isAssignableFrom(eventType)也返回true
*/
return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
}
}
在本项目中 getApplicationListeners(event, type) 返回的监听器会包含Alistener、Blistener、Dlistener、DelegatingApplicationListener。DelegatingApplicationListener会调用Clistener。
4.3 监听了event事件的监听器通过 getApplicationListeners(event, type) 返回了,接下来就是调用监听器的onApplicationEvent(event)方法。
invokeListener(listener, event); 源码
// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#invokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
// 主要代码,调用监听器
doInvokeListener(listener, event);
}
4.3.1 doInvokeListener(listener, event); 源码
// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
// 主要代码,执行监听器的onApplicationEvent(E event);方法
listener.onApplicationEvent(event);
}