我最近不是在写Spring Cloud深度剖析的相关专栏麽,在这期间有收到小伙伴发过来一些问题,A哥通过这段时间收集到的反馈,总结了一下有一个问题非常集中:那便是对Spring Boot应用SpringApplication
的生命周期、事件的理解。有句话A哥不是经常挂嘴边的麽,你对Spring Framework有多了解决定了你对Spring Boot有多了解,你对Spring Boot的了解深度又会制约你去了解Spring Cloud,一环扣一环。因此此问题反馈比较集中是在清理之中的~
为何在Spring Boot中生命周期事件机制如此重要?缘由很简单:Spring Cloud父容器是由该生命周期事件机制来驱动的,而它仅仅是一个典型代表。Spring Cloud构建在Spring Boot之上,它在此基础上构建并添加了一些“Cloud”功能。应用程序事件ApplicationEvent
以及监听器ApplicationListener
是Spring Framework提供的扩展点,Spring Boot对此扩展点利用得非常充分和深入,并且还衍生出了非常多“子”事件类型,甚至自成体系。从ApplicationEvent
衍生出来的子事件类型非常多,例如JobExecutionEvent、RSocketServerInitializedEvent、AuditApplicationEvent...
这里并不会对每个子事件分别介绍(也并无必要),而是集中火力主攻Spring Boot最为重要的一套事件机制:SpringApplication生命周期的事件体系。
正文
本文将以SpringApplication
的启动流程/生命周期各时期发出的Event事件为主线,结合每个生命周期内完成的大事记介绍,真正实现一文让你总览Spring Boot的全貌,这对你深入理解Spring Boot,以及整合进Spring Cloud都将非常重要。
A哥为表诚意,一开始便把SpringApplication
生命周期事件流程图附上,然后再精细化讲解各个事件的详情。
话外音:赶时间的小伙伴可以拿图走人😁,但不建议白嫖哟
生命周期事件流程图
版本说明
由于不同版本、类路径下存在不同包时结果会存在差异,不指明版本的文章都是不够负责任的。因此对导包/版本情况作出如下说明:
-
Spring Boot
:2.2.2.RELEASE。有且仅导入spring-boot-starter-web
和spring-boot-starter-actuator
-
Spring Cloud
:Hoxton.SR1。有且仅导入spring-cloud-context
(注意:并非spring-cloud-starter,并不含有spring-cloud-commons哦)
总的来说:本例导包是非常非常“干净”的,这样在流程上才更有说服力嘛~
SpringApplicationEvent
它是和SpringApplication
生命周期有关的所有事件的父类,@since 1.0.0。
public abstract class SpringApplicationEvent extends ApplicationEvent {
private final String[] args;
public SpringApplicationEvent(SpringApplication application, String[] args) {
super(application);
this.args = args;
}
public SpringApplication getSpringApplication() {
return (SpringApplication) getSource();
}
public final String[] getArgs() {
return this.args;
}
}
它是抽象类,扩展自Spring Framwork的ApplicationEvent
,确保了事件和应用实体SpringApplication
产生关联(当然还有String[] args
)。它有如下实现子类(7个):
每个事件都代表着SpringApplication不同生命周期所处的位置,下面分别进行讲解。
ApplicationStartingEvent:开始启动中
@since 1.5.0,并非1.0.0就有的哦。不过现在几乎没有人用1.5以下的版本了,所以可当它是标准事件。
完成的大事记:
-
SpringApplication
实例已实例化:new SpringApplication(primarySources)
-
它在实例化阶段完成了如下几件“大”事:
-
推断出应用类型
webApplicationType
、main方法所在类 -
给字段initializers赋值:拿到SPI方式配置的
ApplicationContextInitializer
上下文初始化器 -
给字段listeners赋值:拿到SPI方式配置的
ApplicationListener
应用监听器 -
注意:在此阶段(早期阶段)不要过多地使用它的内部状态,因为它可能在生命周期的后期被修改(话外音:使用时需谨慎)
-
-
-
此时,
SpringApplicationRunListener
已实例化:它通过SPI方式指定org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener
。-
若你有自己的运行时应用监听器,使用相同方式配置上即可,均会生效
-
-
由于
EventPublishingRunListener
已经实例化了,因此在后续的事件发送中,均能够触发对应的监听器的执行 - 发送ApplicationStartingEvent事件,触发对应的监听器的执行
监听此事件的监听器们:
默认情况下,有4个监听器监听ApplicationStartingEvent
事件
-
LoggingApplicationListener
:@since 2.0.0。对日志系统抽象LoggingSystem
执行实例化以及初始化之前的操作,默认使用的是基于Logback的LogbackLoggingSystem
-
BackgroundPreinitializer
:启动一个后台进行对一些类进行预热。如ValidationInitializer、JacksonInitializer...
,因为这些组件有第一次惩罚的特点(并且首次初始化均还比较耗时),