【源码】SpringBoot 生命周期及相关事件浅析 二
前言版本ApplicationContextInitializedEventApplicationContextInitializedEvent 对应的监听器
ApplicationPreparedEventApplicationPreparedEvent 对应的监听器
ApplicationStartedEventApplicationStartedEvent 对应的监听器
ApplicationReadyEventApplicationReadyEvent 对应的监听器
ApplicationFailedEvent总结参考
前言
上一章节介绍了 ApplicationStartingEvent ApplicationEnvironmentPreparedEvent 的 生命周期 动作,以及对应 监听器 的行为,本章节继续介绍剩余 事件 相关
版本
SpringBoot 2.3.3.RELEASE
ApplicationContextInitializedEvent
prepareContext(context
, environment
, listeners
, applicationArguments
, printedBanner
);
----------------- prepareContext
-----------------
private void prepareContext(ConfigurableApplicationContext context
, ConfigurableEnvironment environment
,
SpringApplicationRunListeners listeners
, ApplicationArguments applicationArguments
, Banner printedBanner
) {
context
.setEnvironment(environment
);
postProcessApplicationContext(context
);
applyInitializers(context
);
listeners
.contextPrepared(context
);
}
------------ EventPublishingRunListener
------------
public void contextPrepared(ConfigurableApplicationContext context
) {
this.initialMulticaster
.multicastEvent(new ApplicationContextInitializedEvent(this.application
, this.args
, context
));
}
设置 environment 属性容器 的后处理,包括注册 BeanNameGenerator 单例,设置 resourceLoader 属性、设置 conversionService 属性依次执行所有 ApplicationContextInitializer#initialize 方法,ApplicationContextInitializer 即构造方法中 自动装配 的 initializers 属性,共有 7 个 1)DelegatingApplicationContextInitializer:收集所有 environment 中 context.initializer.classes 属性配置的自定义 ApplicationContextInitializer,并执行 initialize 方法,换句话说自定义的 ApplicationContextInitializer 优先级最高 2)SharedMetadataReaderFactoryContextInitializer:注册 CachingMetadataReaderFactoryPostProcessor 后处理器 3)ContextIdApplicationContextInitializer:生成一个 ContextId 类型的 容器标识,并将其注册为 单例 4)ConfigurationWarningsApplicationContextInitializer:注册一个 ConfigurationWarningsPostProcessor 后处理器 5)RSocketPortInfoApplicationContextInitializer:设置 local.rsocket.server.port 属性 6)ServerPortInfoApplicationContextInitializer:设置 local.server.port 等属性 7)ConditionEvaluationReportLoggingListener:设置 ConditionEvaluationReport 属性并注册为 单例发布 ApplicationContextInitializedEvent
ApplicationContextInitializedEvent 对应的监听器
BackgroundPreinitializer:针对 ApplicationContextInitializedEvent 无动作DelegatingApplicationListener:同时发布该事件给所有 自定义监听器
ApplicationPreparedEvent
prepareContext(context
, environment
, listeners
, applicationArguments
, printedBanner
);
----------------- prepareContext
-----------------
private void prepareContext(ConfigurableApplicationContext context
, ConfigurableEnvironment environment
,
SpringApplicationRunListeners listeners
, ApplicationArguments applicationArguments
, Banner printedBanner
) {
ConfigurableListableBeanFactory beanFactory
= context
.getBeanFactory();
beanFactory
.registerSingleton("springApplicationArguments", applicationArguments
);
if (printedBanner
!= null
) {
beanFactory
.registerSingleton("springBootBanner", printedBanner
);
}
if (beanFactory
instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory
) beanFactory
)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding
);
}
if (this.lazyInitialization
) {
context
.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
Set
<Object> sources
= getAllSources();
Assert
.notEmpty(sources
, "Sources must not be empty");
load(context
, sources
.toArray(new Object[0]));
listeners
.contextLoaded(context
);
}
------------ EventPublishingRunListener
------------
public void contextLoaded(ConfigurableApplicationContext context
) {
for (ApplicationListener
<?> listener
: this.application
.getListeners()) {
if (listener
instanceof ApplicationContextAware) {
((ApplicationContextAware
) listener
).setApplicationContext(context
);
}
context
.addApplicationListener(listener
);
}
this.initialMulticaster
.multicastEvent(new ApplicationPreparedEvent(this.application
, this.args
, context
));
}
注册 ApplicationArguments、Banner 对应的 单例设置 allowBeanDefinitionOverriding 属性,由 spring.main 属性控制注册一个 LazyInitializationBeanFactoryPostProcessor 后处理器加载 资源类,这个步骤可以对应成容器的 register 方法,默认情况下由 BeanDefinitionLoader 的成员属性 AnnotatedBeanDefinitionReader annotatedReader 加载主类,主类子路径下的其他配置类则在 ComponentScanAnnotationParser 解析主类时由 ClassPathBeanDefinitionScanner 注册发布 ApplicationPreparedEvent把 SpringApplication 的 监听器 与 容器 绑定起来,同时将 SpringApplication 的 监听器 注册到 容器 中,也就是说 SpringApplication 可以监听到 容器 的相关事件
ApplicationPreparedEvent 对应的监听器
CloudFoundryVcapEnvironmentPostProcessor:略ConfigFileApplicationListener:注册一个 PropertySourceOrderingPostProcessor 后处理器LoggingApplicationListener:注册几个日志相关的 单例BackgroundPreinitializer:针对 ApplicationPreparedEvent 无动作DelegatingApplicationListener:同时发布该事件给所有 自定义监听器
ApplicationStartedEvent
refreshContext(context
);
afterRefresh(context
, applicationArguments
);
stopWatch
.stop();
if (this.logStartupInfo
) {
new StartupInfoLogger(this.mainApplicationClass
).logStarted(getApplicationLog(), stopWatch
);
}
listeners
.started(context
);
------------ EventPublishingRunListener
------------
public void started(ConfigurableApplicationContext context
) {
context
.publishEvent(new ApplicationStartedEvent(this.application
, this.args
, context
));
AvailabilityChangeEvent
.publish(context
, LivenessState
.CORRECT
);
}
在发布 ApplicationStartedEvent 前,有一个很重要的动作 refreshContext,此处调用了 容器 的 refresh 方法,这是 容器 最核心的方法,配置(刷新) 整个 Spring 容器,单例bean 的注册就是发生在此处
关于 容器 的 refresh 方法,可以阅读下面文章
【源码】Spring —— BeanFactory 解读 7 AbstractApplicationContext
发布 ApplicationStartedEvent 后还发布了一个 AvailabilityChangeEvent 事件
ApplicationStartedEvent 对应的监听器
BackgroundPreinitializer:针对 ApplicationStartedEvent 无动作DelegatingApplicationListener:同时发布该事件给所有 自定义监听器
ApplicationReadyEvent
listeners
.running(context
);
------------ EventPublishingRunListener
------------
public void running(ConfigurableApplicationContext context
) {
context
.publishEvent(new ApplicationReadyEvent(this.application
, this.args
, context
));
AvailabilityChangeEvent
.publish(context
, ReadinessState
.ACCEPTING_TRAFFIC
);
}
发布 ApplicationReadyEvent 后还发布了一个 AvailabilityChangeEvent 事件
ApplicationReadyEvent 对应的监听器
BackgroundPreinitializer:在发布 ApplicationEnvironmentPreparedEvent 事件时,此监听器在后台启动一个线程执行 预热 操作,其用到一个 CountDownLatch 使得在 预热 操作执行完成前,所有线程会阻塞在此处。则 ApplicationReadyEvent 事件到达时,如果 预热 完成,预热线程中断
关于 CountDownLatch,可以阅读下面文章
【源码】JUC —— CountDownLatch 浅析
DelegatingApplicationListener:同时发布该事件给所有 自定义监听器
ApplicationFailedEvent
容器 启动失败,则发布 ApplicationFailedEvent
总结
本文屏蔽了大量细节,浅析了 SpringBoot 在 生命周期 发布的所有 事件 及对应的 事件监听器,Spring 基于 后置处理器(BeanPostProcessor) 进行拓展,而 SpringBoot 则引申出 SpringApplication 的抽象概念,基于 事件机制 进行拓展,对于其内部 容器(ApplicationContext) 的则可以通过 监听器 注册 BeanPostProcessor 的方式继续拓展
参考
不懂SpringApplication生命周期事件?那就等于不会Spring Boot嘛
上一篇:【源码】SpringBoot 生命周期及相关事件浅析 一