Github address of SpringBoot Chinese Annotation Project:
How is the SpringApplication object constructed in this article ? SpringBoot source code (eight)
1 Learn from the past
Knowing something new, let ’s briefly review the content of the previous article. In the last article, we analyzed the construction process of the SpringApplication object and a set of SPI mechanisms implemented by SpringBoot .
SpringApplication
The construction process of the object is actually to assign values toSpringApplication
the 6 member variables of the class ;- SpringBoot implements its own SPI mechanism through the following steps:
- 1) First get the thread context class loader;
- 2) Then use the context class loader to load all the SPI extension implementation classes from the
spring.factories
configuration file and put them in the cache ; - 3) According to the SPI interface, remove the corresponding SPI extension implementation class from the cache;
- 4) Instantiate and return the SPI extension implementation class taken from the cache.
2 Introduction
During the SpringBoot startup process, each different startup stage will broadcast different built-in life cycle events, and then the corresponding listener will listen to these events to perform some initialization logic work, such as ConfigFileApplicationListener
listening to onApplicationEnvironmentPreparedEvent
events to load configuration file application.properties
environment variables.
Therefore, this article will analyze the source code of SpringBoot's event monitoring mechanism in the future.
3 SpringBoot broadcast built-in life cycle event process analysis
In order to explore the SpringBoot broadcast built-in life cycle event process, let us review the SpringBoot startup process code:
// SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 【0】新建一个SpringApplicationRunListeners对象用于发射SpringBoot启动过程中的生命周期事件
SpringApplicationRunListeners listeners = getRunListeners(args);
// 【1】》》》》》发射【ApplicationStartingEvent】事件,标志SpringApplication开始启动
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 【2】》》》》》发射【ApplicationEnvironmentPreparedEvent】事件,此时会去加载application.properties等配置文件的环境变量,同时也有标志环境变量已经准备好的意思
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 【3】》》》》》发射【ApplicationContextInitializedEvent】事件,标志context容器被创建且已准备好
// 【4】》》》》》发射【ApplicationPreparedEvent】事件,标志Context容器已经准备完成
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 【5】》》》》》发射【ApplicationStartedEvent】事件,标志spring容器已经刷新,此时所有的bean实例都已经加载完毕
listeners.started(context);
callRunners(context, applicationArguments);
}
// 【6】》》》》》发射【ApplicationFailedEvent】事件,标志SpringBoot启动失败
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 【7】》》》》》发射【ApplicationReadyEvent】事件,标志SpringApplication已经正在运行即已经成功启动,可以接收服务请求了。
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
复制代码
It can be seen that SpringBoot will first create a new SpringApplicationRunListeners
object for launching various life cycle events during the SpringBoot startup process, such as launch ApplicationStartingEvent
, ApplicationEnvironmentPreparedEvent
and ApplicationContextInitializedEvent
other events, and then the corresponding listener will perform some initialization logic during the SpringBoot startup process . So, when are the listeners that listen to these SpringBoot lifecycle events loaded and instantiated? Remember the analysis SpringApplication
process of the last article ? That's right, these listeners that perform initialization logic are loaded and instantiated in the configuration file SpringApplication
according to the ApplicationListener
interface during the construction process spring.factories
.
3.1 Preparing for broadcasting SpringBoot's built-in lifecycle events
3.1.1 Load ApplicationListener listener implementation class
Let's review how the SpringApplication object is constructed? SpringBoot source code (eight) article talks about this code SpringApplication
when constructing objects setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
.
This code do is from the spring.factories
load in the ApplicationListener
event listener interface SPI extended implementation class and then add to SpringApplication
the object listeners
in the collection for subsequent listening SpringBoot startup events, initialization logic to perform some work.
The specific listeners at the time of SpringBoot startup have implemented ApplicationListener
interfaces, which are spring.factories
partially configured as follows:
However, during debugging, the listeners are loaded from all spring.factories configuration files, and finally 10 listeners are loaded. As shown below:
3.1.2 Load SPI extension class EventPublishingRunListener
As mentioned earlier, in the startup process of SpringBoot, a new SpringApplicationRunListeners
object will be created first for launching the life cycle events in the startup process of SpringBoot. That is, let us look at SpringApplicationRunListeners listeners = getRunListeners(args);
this code:
// SpringApplication.java
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 构造一个由SpringApplication.class和String[].class组成的types
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 1) 根据SpringApplicationRunListener接口去spring.factories配置文件中加载其SPI扩展实现类
// 2) 构建一个SpringApplicationRunListeners对象并返回
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
复制代码
We will focus on getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)
this sentence of code. getSpringFactoriesInstances
We are already familiar with this method. We have analyzed this method in detail in the previous article when analyzing the SPI mechanism of Spring Boot. It can be seen that SpringBoot is now loading the corresponding SPI extension implementation class according to SpringApplicationRunListener
this SPI interface spring.factories
. Let's go directly to spring.factories
see SpringApplicationRunListener
which SPI implementation classes are there:
SpringApplicationRunListener
only
EventPublishingRunListener
the SPI implementation class
EventPublishingRunListener
this guy is especially important during startup SpringBoot, the emission lifecycle events different SpringBoot by its different stages of the startup process in SpringBoot,
that is, SpringApplicationRunListeners
the object does not assume responsibility broadcast events, In the end, EventPublishingRunListener
the buddy was entrusted to broadcast the event.
Because from spring.factories
the load EventPublishingRunListener
when the class will instantiate the class, then we follow up EventPublishingRunListener
the source code to see how it is to undertake emission SpringBoot life cycle events that responsibility?
// EventPublishingRunListener.java
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
/**
* 拥有一个SimpleApplicationEventMulticaster事件广播器来广播事件
*/
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 新建一个事件广播器SimpleApplicationEventMulticaster对象
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 遍历在构造SpringApplication对象时从spring.factories配置文件中获取的事件监听器
for (ApplicationListener<?> listener : application.getListeners()) {
// 将从spring.factories配置文件中获取的事件监听器们添加到事件广播器initialMulticaster对象的相关集合中
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public int getOrder() {
return 0;
}
// 》》》》》发射【ApplicationStartingEvent】事件
@Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
// 》》》》》发射【ApplicationEnvironmentPreparedEvent】事件
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
// 》》》》》发射【ApplicationContextInitializedEvent】事件
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
this.application, this.args, context));
}
// 》》》》》发射【ApplicationPreparedEvent】事件
@Override
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));
}
// 》》》》》发射【ApplicationStartedEvent】事件
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}
// 》》》》》发射【ApplicationReadyEvent】事件
@Override
public void running(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationReadyEvent(this.application, this.args, context));
}
// 》》》》》发射【ApplicationFailedEvent】事件
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application,
this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// call all of the context's listeners instead
if (context instanceof AbstractApplicationContext) {
for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
.getApplicationListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
// ...省略非关键代码
}
复制代码
You can see the EventPublishingRunListener
class implements SpringApplicationRunListener
the interface, SpringApplicationRunListener
the interface defines the interface method of transmitting life cycle events when SpringBoot start, while the EventPublishingRunListener
class to achieve it is through SpringApplicationRunListener
the interface starting
, environmentPrepared
and contextPrepared
broadcast SpringBoot different life cycle events and so on, we look at the direct SpringApplicationRunListener
interface to source good Off:
// SpringApplicationRunListener.java
public interface SpringApplicationRunListener {
void starting();
void environmentPrepared(ConfigurableEnvironment environment);
void contextPrepared(ConfigurableApplicationContext context);
void contextLoaded(ConfigurableApplicationContext context);
void started(ConfigurableApplicationContext context);
void running(ConfigurableApplicationContext context);
void failed(ConfigurableApplicationContext context, Throwable exception);
}
复制代码
We then analyze EventPublishingRunListener
this class, we can see that it has an important member attribute initialMulticaster
, the member attribute is a SimpleApplicationEventMulticaster
class object, this class is responsible for broadcasting the life cycle events of SpringBoot startup, that isEventPublishingRunListener
SimpleApplicationEventMulticaster
, the object does not assume the responsibility of broadcasting events, In the end, the buddy was entrusted to broadcast the event. EventPublishingRunListener
It can also be seen from the source code that starting
, in methods such as He environmentPrepared
and so contextPrepared
on, it is also by calling methods of SimpleApplicationEventMulticaster
class objects multicastEvent
to broadcast events.
Consider that when the event is launched during the SpringBoot startup, the event broadcaster delegates responsibilities layer by layer, which is initially
SpringApplicationRunListeners
assumed by the object, and then theSpringApplicationRunListeners
object delegates the responsibility of broadcasting events to theEventPublishingRunListener
object, and finally theEventPublishingRunListener
object delegates the responsibility of broadcasting events to theSimpleApplicationEventMulticaster
object. Why do you delegate this to layers? This is worth thinking about.
From the foregoing mentioned spring.factories
loading out EventPublishingRunListener
when the class is instantiated, the instantiated bound by EventPublishingRunListener
the constructor to be instantiated, we next analyzed the EventPublishingRunListener
constructor source:
// EventPublishingRunListener.java
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 新建一个事件广播器SimpleApplicationEventMulticaster对象
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 遍历在构造SpringApplication对象时从spring.factories配置文件中获取的事件监听器
for (ApplicationListener<?> listener : application.getListeners()) {
// 将从spring.factories配置文件中获取的事件监听器们添加到事件广播器initialMulticaster对象的相关集合中
this.initialMulticaster.addApplicationListener(listener);
}
}
复制代码
It can be seen in EventPublishingRunListener
the constructor there is a for
loop iterates until the spring.factories
load of the listeners were then added to the collection cached for later taken directly from this set out to when various events broadcast instead Then go spring.factories
to load, improve efficiency.
3.2 Broadcast SpringBoot's built-in life cycle events
After spring.factories
loading and instantiating the EventPublishingRunListener
object from the configuration file, a series of SpringBoot built-in life cycle events will be launched during the SpringBoot startup process. Let us review the source code during the SpringBoot startup process:
// SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 【0】新建一个SpringApplicationRunListeners对象用于发射SpringBoot启动过程中的生命周期事件
SpringApplicationRunListeners listeners = getRunListeners(args);
// 【1】》》》》》发射【ApplicationStartingEvent】事件,标志SpringApplication开始启动
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 【2】》》》》》发射【ApplicationEnvironmentPreparedEvent】事件,此时会去加载application.properties等配置文件的环境变量,同时也有标志环境变量已经准备好的意思
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 【3】》》》》》发射【ApplicationContextInitializedEvent】事件,标志context容器被创建且已准备好
// 【4】》》》》》发射【ApplicationPreparedEvent】事件,标志Context容器已经准备完成
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 【5】》》》》》发射【ApplicationStartedEvent】事件,标志spring容器已经刷新,此时所有的bean实例都已经加载完毕
listeners.started(context);
callRunners(context, applicationArguments);
}
// 【6】》》》》》发射【ApplicationFailedEvent】事件,标志SpringBoot启动失败
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 【7】》》》》》发射【ApplicationReadyEvent】事件,标志SpringApplication已经正在运行即已经成功启动,可以接收服务请求了。
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
复制代码
It can be seen that during the boot process of Spring Boot, a total of 7 different types of life cycle events will be emitted to mark the different boot phases of Spring Boot. At the same time, these life cycle event listeners will also perform some initialization logic during the boot process The initialization logic of these listeners will be analyzed in the next article. The following are the types of events to be emitted ApplicationFailedEvent
during the SpringBoot startup process, in which an exception will be emitted during the SpringBoot startup process:
ApplicationStartingEvent
ApplicationEnvironmentPreparedEvent
ApplicationContextInitializedEvent
ApplicationPreparedEvent
ApplicationStartedEvent
ApplicationFailedEvent
ApplicationReadyEvent
Let's take listeners.starting();
this code as an example and look at EventPublishingRunListener
the source code of the object emission event:
// SpringApplicationRunListeners.java
public void starting() {
// 遍历listeners集合,这里实质取出的就是刚才从spring.factories中取出的SPI实现类EventPublishingRunListener
// 而EventPublishingRunListener对象承担了SpringBoot启动过程中负责广播不同的生命周期事件
for (SpringApplicationRunListener listener : this.listeners) {
// 调用EventPublishingRunListener的starting方法来广播ApplicationStartingEvent事件
listener.starting();
}
}
复制代码
Continue to follow listener.starting();
the source code:
EventPublishingRunListener.java
// 》》》》》发射【ApplicationStartingEvent】事件
public void starting() {
// EventPublishingRunListener对象将发布ApplicationStartingEvent这件事情委托给了initialMulticaster对象
// 调用initialMulticaster的multicastEvent方法来发射ApplicationStartingEvent事件
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
复制代码
As you can see, the EventPublishingRunListener
object ApplicationStartingEvent
delegates this matter to the SimpleApplicationEventMulticaster
object initialMulticaster
, and the initialMulticaster
object will eventually call its multicastEvent
methods to emit ApplicationStartingEvent
events. Regarding SimpleApplicationEventMulticaster
how the class broadcasts events, how has the author implemented the event monitoring mechanism in Spring? This article of Spring source code (2) has been analyzed in detail and will not be repeated here.
The source code for launching other life cycle events during the SpringBoot startup process is not analyzed here
4 Summary of SpringBoot's built-in life cycle events
Well, I have analyzed various life cycle events to be launched during the SpringBoot startup process. The following table summarizes:
5 Summary
This is the end of the source code analysis of the broadcast lifecycle events during the SpringBoot startup process. The next article will continue to introduce the listeners who listen to these lifecycle events. We review the key points in this article:
SpringBoot will launch 7 types of life cycle events during the startup process, marking different startup stages, and then the corresponding listeners will listen to these events to perform some initialization logic work.
[Source Notes] Github source code analysis project is online! ! ! The following is the Github address of the note:
Likes and reposts are the biggest motivation for the author!
Public number [ source notes ], focusing on the source code analysis of the Java back-end series framework.