SpringBoot运行流程源码分析
上一章中我们分析了 SpringApplication 类实例化的源代码,在此过程中完成了基本配置文件的加载和实例化。当 SpringApplication 对象被创建之后, 通过调用其 run 方法来进行SpringBoot 的启动和运行,至此正式开启了 SpringApplication 的生命周期。
本章介绍的内容同样是 Spring Boot 运行的核心流程之一,我们将会围绕
SpringApplicationRunListeners、ApplicationArguments、ConfigurableEnvironment 以及 应用上下文信息等部分展开讲解。
run方法核心流程
在分析和学习整个 run 方法的源代码及操作之前,我们先通过图 4-1 所示的流程图来看一下SpringApplication 调用的 run 方法处理的核心操作都包含哪些。然后,后面的章节我们再逐步细化分析每个过程中的源代码实现。
上面的流程图可以看出,SpringApplication 在 run 方法中重 点做了以下操作。
.获取监听器和参数配置。
.打印 Banner 信息。
.创建并初始化容器。
监听器发送通知。
当然,除了核心操作,run 方法运行过程中还涉及启动时长统计、异常报告、启动日志、异常处理等辅助操作。
对照流程图,我们再来整体看一下入口 run 方法的源代码,核心部分的功能已通过注释的形式进行说明。
public ConfigurableApplicationContext run(String... args) {
//创建 stopwatch 对象, 用于统 i 计 run 方法启动时长
StopWatch stopWatch = new StopWatch();
//启动统计
stopwatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> except ionReporters = new Arraylis
t<>();
//配置 headless 属性
configureHeadlessProperty();
//获得 SpringAppl icat ionRunL istener 数组
//该数组封装 FSpringAppl icat ionRunL isteners 对象的 L isteners 中
SpringApplicationRunListeners listeners = getRunListeners(args);
//启动监听,遍历 SpringAppl icat ionRunL istener 数组每个元素,并执行
listeners .starting();
try {创建 Appl icat ionArguments 对象
ApplicationArguments applicationArguments = new DefaultApplicationArgum
ents(
args);
//加载属性配置,包括所有的配置属性(如: appl icat ion. properties 中和外部的属
性配置)
Conf igurableEnvironment environment = prepareEnvironment(listeners,
applicationArg
uments);
configureIgnoreBeanInfo( environment);
//打 Banner
Banner printedBanner = printBanner ( environment);
//创建容器
context = createApplicationContext();
//异常报告器
exceptionReporters = getSpringFactoriesInstances(
Spr ingBootExcept ionReporter .class ,
new Class[] { ConfigurableApplicat ionContext.class }, context);
//准备容器,组件对象之间进行关联
prepareContext(context, environment, listeners, applicationArguments, p
rintedBanner);
// 初始化容器
refreshContext(context);
//初始化操作之后执行,默认实现为空
afterRefresh( context, applicationArguments);
//停止时长统计
stopWatch. stop();
//打印启动日志
if (this. logStartupInfo) {
new StartupInfoLogger(this . mainApplicat ionClass)
.logStarted(getApplicationLog(), stopwatch);
//通知监昕器:容器启动完成
listeners . started( context);
//调用 Appl icat ionRunner 和 CommandL ineRunner 的运行方法。
callRu