目录
一、简介
二、SpringBoot事件监听机制
1)加载ApplicationListener监听器实现类
2)获取运行监听器EventPublishingRunListener
3)发布事件
4)Spring事件发布multicastEvent()
一、简介
接下来我们分析下SpringBoot的事件监听机制的源码。
二、SpringBoot事件监听机制
1)加载ApplicationListener监听器实现类
在执行run()方法运行SpringApplication之前,首先得先创建一个SpringApplication对象,我们查看其构造方法:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 传递的resourceLoader为null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 记录主方法的配置类名称
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 推导出当前启动的项目的类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化. 并将加载的数据存储在了 initializers 成员变量中。
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化监听器,并将加载的监听器实例对象存储在了listeners成员变量中
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 反推出main方法所在的Class对象
this.mainApplicationClass = deduceMainApplicationClass();
}
我们看到,在SpringApplication的构造方法中,通过setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class))初始化一些监听器,getSpringFactoriesInstances()这个方法相信大家都比较熟悉了,就是从项目中所有的"META-INF/spring.factories"文件中找到ApplicationListener对应的监听器,获取成功后,将这些监听器赋值给SpringApplication#listeners属性保存起来。
例如spring-boot/META-INF/spring.factories中配置了9个ApplicationListener,如下图:
在springboot应用启动时,它会从所有的spring.factories配置文件中加载ApplicationListener,如下图:
经过这一步之后,已经将获取到的所有ApplicationListener保存到SpringApplication对象的listeners属性中,后续使用的时候,我们就可以直接从SpringApplication对象中拿出来。
2)获取运行监听器EventPublishingRunListener
我们看一下运行SpringApplication的run()方法:
// 运行 Spring 应用程序,创建并刷新一个新的ApplicationContext
public ConfigurableApplicationContext run(String... args) {
// 创建一个任务执行观察器,用于统计run启动过程花了多少时间
StopWatch stopWatch = new StopWatch();
// 记录开始时间
stopWatch.start();
ConfigurableApplicationContext context = null;
// exceptionReporters集合用来存储异常报告器,用来报告SpringBoot启动过程的异常
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 设置了一个名为java.awt.