目录
扫描org.springframework.context.ApplicationListener 指定的类
内置的监听
spring boot 中的监听
spring boot autoconfigure中的监听
spring boot context 中的监听
将加载的监听进行排序
spring boot 中的监听
spring boot context 中的监听
监听执行
监听加载到SpringApplicationRunListeners 中
调用 SpringApplicationRunListeners 的environmentPrepared()进行监听调用
总结
在前面的文章基础上
https://blog.csdn.net/zlpzlpzyd/article/details/136065211
spring 相关的项目中的代码一直在变,下面以spring boot2.3.12.RELEASE 以及对应的spring cloudHoxton.SR12 进行说明。
spring boot 在启动时会通过SpringFactoriesLoader 加载 classpath 下META-INF/spring.factories 中的对应的类。
扫描org.springframework.context.ApplicationListener 指定的类
其中监听对应的接口为ApplicationListener,对应的监听是其实现类实现对应的功能。
内置的监听
spring boot 中的监听
org.springframework.context.ApplicationListener=\org.springframework.boot.ClearCachesApplicationListener,\org.springframework.boot.builder.ParentContextCloserApplicationListener,\org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\org.springframework.boot.context.FileEncodingApplicationListener,\org.springframework.boot.context.config.AnsiOutputApplicationListener,\org.springframework.boot.context.config.ConfigFileApplicationListener,\org.springframework.boot.context.config.DelegatingApplicationListener,\org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\org.springframework.boot.context.logging.LoggingApplicationListener,\org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
除了ClearCachesApplicationListener 和LiquibaseServiceLocatorApplicationListener 都实现了 spring 的接口Ordered。
spring boot autoconfigure中的监听
org.springframework.context.ApplicationListener=\org.springframework.boot.autoconfigure.BackgroundPreinitializer
只有一个BackgroundPreinitializer,通过注解 @Order 指定了顺序。
spring boot context 中的监听
org.springframework.context.ApplicationListener=\org.springframework.cloud.bootstrap.BootstrapApplicationListener,\org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\org.springframework.cloud.context.restart.RestartListener
都实现了spring 的接口Ordered。
将加载的监听进行排序
在SpringApplication#getSpringFactoriesInstances() 中通过 AnnotationAwareOrderComparator.sort() 进行处理
其中排序逻辑在父类OrderComparator 中进行实现。
如果当前监听实现了接口Ordered,则按照对应的编号进行比较,否则直接返回最低优先级,即Integer.MAX_VALUE。
findOrder() 在子类AnnotationAwareOrderComparator 中进行重写,用于处理使用注解@Order 标记的类。
spring boot 中的监听
对应的监听排序如下
CloudFoundryVcapEnvironmentPostProcessorInteger.MIN_VALUE + 10 - 1ConfigFileApplicationListenerInteger.MIN_VALUE + 10AnsiOutputApplicationListenerInteger.MIN_VALUE + 10 + 1LoggingApplicationListenerInteger.MIN_VALUE + 20ClasspathLoggingApplicationListenerInteger.MIN_VALUE + 20 + 1DelegatingApplicationListener0ParentContextCloserApplicationListenerInteger.MAX_VALUE - 10FileEncodingApplicationListenerInteger.MAX_VALUEClearCachesApplicationListenerInteger.MAX_VALUELiquibaseServiceLocatorApplicationListenerInteger.MAX_VALUE
实际执行结果
spring boot context 中的监听
对应的监听排序如下
BootstrapApplicationListenerInteger.MIN_VALUE + 5LoggingSystemShutdownListenerInteger.MIN_VALUE + 5 + 1RestartListener0
结合 spring boot 启动后的顺序如下
BootstrapApplicationListenerInteger.MIN_VALUE + 5LoggingSystemShutdownListenerInteger.MIN_VALUE + 5 + 1CloudFoundryVcapEnvironmentPostProcessorInteger.MIN_VALUE + 10 - 1ConfigFileApplicationListenerInteger.MIN_VALUE + 10AnsiOutputApplicationListenerInteger.MIN_VALUE + 10 + 1LoggingApplicationListenerInteger.MIN_VALUE + 20ClasspathLoggingApplicationListenerInteger.MIN_VALUE + 20 + 1DelegatingApplicationListener0RestartListener0ParentContextCloserApplicationListenerInteger.MAX_VALUE - 10FileEncodingApplicationListenerInteger.MAX_VALUEClearCachesApplicationListenerInteger.MAX_VALUELiquibaseServiceLocatorApplicationListenerInteger.MAX_VALUE
实际执行结果
可以看到,引入 spring cloud 组件后,默认执行 BootstrapApplicationListener 中的逻辑加载bootstrap 相关的配置。
监听执行
监听加载到SpringApplicationRunListeners 中
上面的监听先加载到了SpringApplicationRunListeners,内部通过一个集合存储SpringApplicationRunListener 的实现类EventPublishingRunListener 进行存储以进行后续处理。
通过SpringApplication#getRunListeners() 进行加载
通过反射创建,构造器参数中传入当前类SpringApplication。
将SpringApplication 中加载的监听添加到接口 ApplicationEventMulticaster 的实现类。
SimpleApplicationEventMulticaster 的父类 AbstractApplicationEventMulticaster 的内部类 DefaultListenerRetriever 的变量 applicationListeners 中。
调用 SpringApplicationRunListeners 的environmentPrepared()进行监听调用
调用SpringApplicationRunListeners#environmentPrepared() 间接调用SpringApplicationRunListener 的environmentPrepared(),对应的实现类为EventPublishingRunListener。
执行SpringApplication#prepareEnvironment()
调用SimpleApplicationEventMulticaster 的multicastEvent()
调用SpringApplicationRunListener#environmentPrepared()
调用SimpleApplicationEventMulticaster#multicastEvent(),参数为事件ApplicationEnvironmentPreparedEvent。
循环遍历监听,看是否支持对应的事件
由于排序靠前的监听中ConfigFileApplicationListener 中引入了ApplicationEnvironmentPreparedEvent,所以优先处理。
调用了ConfigFileApplicationListener#onApplicationEvent() 后,处理步骤如下
判断当前事件是否为ApplicationEnvironmentPreparedEvent 的实例,符合条件,执行后续处理。
加载 classpath 中META-INF/spring.factories 中指定的EnvironmentPostProcessor 的实现类。
加载当前类为到EnvironmentPostProcessor 中并进行排序,ConfigFileApplicationListener 实现了接口 EnvironmentPostProcessor。
执行EnvironmentPostProcessor#postProcessEnvironment() 进行配置文件加载。
总结
综合上述表述,如果引入了 BootstrapApplicationListener 则优先加载,但是在源码中发现如下
正好对应了我们平时写的 spring boot 启动类,可知,在启动时,如果引入了 spring cloud 组件,会先创建一个子容器来加载对应的配置,然后传递到父容器中进行参数传递,完成参数加载。