【源码】SpringBoot 生命周期及相关事件浅析 一
前言版本SpringApplicationSpringApplication 启动SpringApplication 实例构造SpringApplication.run
ApplicationStartingEventApplicationStartingEvent 对应的监听器
ApplicationEnvironmentPreparedEventApplicationEnvironmentPreparedEvent 对应的监听器
总结
前言
阅读本系列章节前,建议复习一下 Spring事件、事件监听器、事件发布 相关
【源码】Spring —— ApplicationEvent ApplicationListener ApplicationEventMulticaster
SpringBoot 提供了事件父类 SpringApplicationEvent,继承自 ApplicationEvent
其下定义了 7 个事件,本系列结合部分源码解读 SpringBoot 何时发布这些 事件?对应的 事件监听器 都做了什么?
版本
SpringBoot 2.3.3.RELEASE
SpringApplication
SpringApplication,Spring 应用的抽象。在 SpringBoot 中,我们可以通过一个简单的 main 方法,来启动一个 Spring 应用
SpringApplication 启动
public static ConfigurableApplicationContext
run(Class
<?> primarySource
, String
... args
) {
return run(new Class[]{primarySource
}, args
);
}
public static ConfigurableApplicationContext
run(Class
<?>[] primarySources
, String
[] args
) {
return (new SpringApplication(primarySources
)).run(args
);
}
即创建一个 SpringApplication 实例,调用 run 方法
SpringApplication 实例构造
public SpringApplication(ResourceLoader resourceLoader
, Class
<?>... primarySources
) {
this.resourceLoader
= resourceLoader
;
Assert
.notNull(primarySources
, "PrimarySources must not be null");
this.primarySources
= new LinkedHashSet<>(Arrays
.asList(primarySources
));
this.webApplicationType
= WebApplicationType
.deduceFromClasspath();
setInitializers((Collection
) getSpringFactoriesInstances(ApplicationContextInitializer
.class));
setListeners((Collection
) getSpringFactoriesInstances(ApplicationListener
.class));
this.mainApplicationClass
= deduceMainApplicationClass();
}
属性的初始化,其中 initializers 和 listeners 从 spring.factories 文件读取加载
SpringApplication.run
public ConfigurableApplicationContext
run(String
... args
) {
StopWatch stopWatch
= new StopWatch();
stopWatch
.start();
ConfigurableApplicationContext context
= null
;
Collection
<SpringBootExceptionReporter> exceptionReporters
= new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners
= getRunListeners(args
);
listeners
.starting();
try {
ApplicationArguments applicationArguments
= new DefaultApplicationArguments(args
);
ConfigurableEnvironment environment
= prepareEnvironment(listeners
, applicationArguments
);
configureIgnoreBeanInfo(environment
);
Banner printedBanner
= printBanner(environment
);
context
= createApplicationContext();
exceptionReporters
= getSpringFactoriesInstances(SpringBootExceptionReporter
.class,
new Class[] { ConfigurableApplicationContext
.class }, context
);
prepareContext(context
, environment
, listeners
, applicationArguments
, printedBanner
);
refreshContext(context
);
afterRefresh(context
, applicationArguments
);
stopWatch
.stop();
if (this.logStartupInfo
) {
new StartupInfoLogger(this.mainApplicationClass
).logStarted(getApplicationLog(), stopWatch
);
}
listeners
.started(context
);
callRunners(context
, applicationArguments
);
}
catch (Throwable ex
) {
handleRunFailure(context
, ex
, exceptionReporters
, listeners
);
throw new IllegalStateException(ex
);
}
try {
listeners
.running(context
);
}
catch (Throwable ex
) {
handleRunFailure(context
, ex
, exceptionReporters
, null
);
throw new IllegalStateException(ex
);
}
return context
;
}
此处先贴出 run 方法的所有代码,可以看到 SpringApplication 在完成对应的动作后就会发布对应的 事件,触发对应的 监听器,监听器 可能输出对应的日志,也可能类似于 Spring 的 后置处理器,对 容器 environment 等进行配置、处理,也可能 无动作
接下来我们依次解读发布的 事件,以及对应的 监听器
ApplicationStartingEvent
SpringApplicationRunListeners listeners
= getRunListeners(args
);
listeners
.starting();
------------ EventPublishingRunListener
------------
public void starting() {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(this.application
, this.args
));
}
这里实例化了 SpringApplicationRunListeners,SpringApplicationRunListeners 就是对内部 SpringApplicationRunListener 的一层封装,之后 SpringApplication 生命周期相关的 事件 将由 SpringApplicationRunListeners 来发布,其本质就是循环调用内部所有 SpringApplicationRunListener 对应方法SpringApplicationRunListener 就是一个模板接口,定义了 SpringApplication 生命周期要发布 事件 的模板,SpringBoot 提供了一个实现类 EventPublishingRunListener,在上述代码的 getRunListeners 方法中,自动装配并创建 EventPublishingRunListener 的示例返回EventPublishingRunListener 发布 事件 是委托给内部的 SimpleApplicationEventMulticaster 来实现的,即就是将 事件 发布给对应 事件监听器这里发布了 ApplicationStartingEvent 事件
ApplicationStartingEvent 对应的监听器
监听 ApplicationStartingEvent 的监听器有
LoggingApplicationListener:日志相关BackgroundPreinitializer:针对 ApplicationStartingEvent 无动作DelegatingApplicationListener:针对 ApplicationStartingEvent 无动作LiquibaseServiceLocatorApplicationListener:liquibase 相关
ApplicationEnvironmentPreparedEvent
ConfigurableEnvironment environment
= prepareEnvironment(listeners
, applicationArguments
);
---------------- prepareEnvironment
----------------
private ConfigurableEnvironment
prepareEnvironment(SpringApplicationRunListeners listeners
,
ApplicationArguments applicationArguments
) {
ConfigurableEnvironment environment
= getOrCreateEnvironment();
configureEnvironment(environment
, applicationArguments
.getSourceArgs());
ConfigurationPropertySources
.attach(environment
);
listeners
.environmentPrepared(environment
);
bindToSpringApplication(environment
);
if (!this.isCustomEnvironment
) {
environment
= new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment
,
deduceEnvironmentClass());
}
ConfigurationPropertySources
.attach(environment
);
return environment
;
}
------------ EventPublishingRunListener
------------
public void environmentPrepared(ConfigurableEnvironment environment
) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application
, this.args
, environment
));
}
首先创建了 ConfigurableEnvironment 实例初步配置后,发布 ApplicationEnvironmentPreparedEvent 事件,该 事件 相关的 监听器 动作比较大,SringBoot 强大的配置能力也基于此实现后续动作,比如绑定相关配置到当前 SpringApplication 实例,之后返回配置好的 ConfigurableEnvironment 实例
继续阅读之前,建议了解以下 Spring Environment
【源码】Spring —— Environment 解读
ApplicationEnvironmentPreparedEvent 对应的监听器
ConfigFileApplicationListener:在这个 监听器 中,自动装配其他 4 个 EnvironmentPostProcessor(ConfigFileApplicationListener 本身也是一个 EnvironmentPostProcessor),然后依次调用了它们的 postProcessEnvironment 方法 1)SystemEnvironmentPropertySourceEnvironmentPostProcessor:将 environment 中名为 systemEnvironment 的 PropertySource 替换为 OriginAwareSystemEnvironmentPropertySource 类型的(可调用 getOrigin 方法获取对应的 SystemEnvironmentOrigin) 2)SpringApplicationJsonEnvironmentPostProcessor:解析 environment 所有 PropertySource 中的 spring.application.json 和 SPRING_APPLICATION_JSON 属性 3)CloudFoundryVcapEnvironmentPostProcessor:SpringCloud 相关 4)ConfigFileApplicationListener:该监听器本身也是最核心的 EnvironmentPostProcessor:给 environment 添加一个名为 random 的 PropertySource;加载 environment 的 activeProfiles 属性;加载配置文件的所有配置到 environment 的 propertySources 中 5)DebugAgentEnvironmentPostProcessor:Spring Reactor 相关AnsiOutputApplicationListener:解析 spring.output.ansi.enabled 属性LoggingApplicationListener:日志相关ClasspathLoggingApplicationListener:日志输出 classpath 信息BackgroundPreinitializer:启动一个线程异步执行 实例化DefaultFormattingConversionService、实例化AllEncompassingFormHttpMessageConverter 等动作,该行为可以通过 spring.backgroundpreinitializer.ignore 属性控制DelegatingApplicationListener:解析 context.listener.classes 属性对应的所有自定义的 事件监听器,在这之后的事件也会同样发布给这些 监听器。换句话说,用户可以 自定义监听器 监听 ApplicationEnvironmentPreparedEvent 及其之后的所有 ApplicationEvent 事件(注意,监听不到 ApplicationStartingEvent)FileEncodingApplicationListener:如果设置了 spring.mandatory-file-encoding 属性,则当其与系统的 file.encoding 属性不同时,输出相关日志信息
总结
本章节介绍了 ApplicationStartingEvent ApplicationEnvironmentPreparedEvent 的 生命周期 动作,以及对应 监听器 的行为,避免篇幅太长,下章节继续
下一篇:【源码】SpringBoot 生命周期及相关事件浅析 二