
SpringBoot运行流程,首先从 Spring Application调用 run 方法开始,如下所示:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
在main主方法中:调用了SpringApplication的run方法,该方法完成了整个SpringBoot的启动流程。
下面让我们一起来看一下这个方法执行过程中都做了哪些工作:
//SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
由上面的代码可以指定,run方法在SpringApplication是一个静态方法,该方法会将传入的启动类(Application.class)作为SpringApplication的构造参数来创建一个SpringApplication的实例。
下面我们看一下run方法的代码实现:
//SpringApplication的run方法
public ConfigurableApplicationContext run(String... args) {
//创建StopWatch对象用于统计run方法的执行耗时
StopWatch stopWatch = new StopWatch();
//调用start方法表示开始启动计时
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//通过SPI机制加载所有的SpringApplicatoinRunListener监听器
//SpringBoot启动过程的不同阶段会回调该监听器的不同方法
SpringApplicationRunListeners listeners = getRunListeners(args);
//调用SpringApplicatoinRunListener的starting方法
listeners.starting();
try {
//将SpringApplication的启动参数封装为ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//创建SpringBoot应用使用的环境变量对象,内部会根据webApplicationType创建不同的环境对象,
//这里会创建StandardServletEnvironment对象
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//打印banner,默认是在管控台打印SpringBoot
Banner printedBanner = printBanner(environment);
//创建使用的ApplicationContext上下文对象,这里会根据webApplicationType创建不同的对象上下文对象
//这里创建的是AnnotationConfigServletWebServerApplicationContext对象
context = createApplicationContext();
//通过SPI机制加载SpringBoot的异常报告对象SpringBootExceptionReporter
//当SpringBoot启动过程中抛出异常时,会通过该对象打印错误日志
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//ApplicationContext上下文对象创建完毕后,会调用prepareContext为ApplicationContext做一些准备工作
//比如为ApplicationContext设置环境变量,回调ApplicationContextInitializer对象的initialize方法等
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//调用ApplicationContext的refresh方法,启动整个Spring应用程序
refreshContext(context);
//停止StopWatch计时器
stopWatch.stop();
//调用SpringApplcationListener对象的started监听方法
listeners.started(context);
//回调Spring中的的ApplicationRunner对象和CommandLineRunner对象
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
//抛出异常,则使用SpringExceptionReporter打印异常报告
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//启动成功,则调用SpringApplicationListener对象的running监听方法
listeners.running(context);
}
catch (Throwable ex) {
//抛出异常,则使用SpringExceptionReporter打印异常报告
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
//返回创建的ApplicationContext应用上下文
return context;
}
SpringBoot运行流程,大致分为如下11大执行流程步骤:

1)创建 Spring Application 实例,调用 run 方法,同时将启动入口类作 为参数传递进去;
2)通过 Spring Factories Loader 加载 META-INF/spring.factories 文 件;
3)然后由 SpringApplicationRunListener 来发出 starting 消息;
4)创建参数,并配置当前 SpringBoot 应用需要使用的 Environment 实 例;
5)完成之后,依然由 SpringApplicationRunListener 来发出 environmentPrepared 消息;
6)创建 Spring 的应用上下文实例:ApplicationContext,初始化该实例 并设置应用环境配置实例:Environment,同时加载相关的配置项;
7)由 SpringApplicationRunListener 发出 contextPrepared 消息,告 知 SpringBoot 应用当前使用的 ApplicationContext 已准备完毕;
8)将各种 Bean 组件装载入 Spring 的 IO 容器/应用上下文: ApplicationContext 中,继续由 SpringApplicationRunListener 来发出 contextLoaded 消息,告知 SpringBoot 应用当前使用的 ApplicationContext 已准备完毕;
9)重新刷新 Refresh Spring 的应用上下文实例:ApplicationContext, 完成 IOC 容器可用的最后一步;
10)由 SpringApplicationRunListener 发出 started 消息,完成最终的 程序的启动;
11)由 SpringApplicationRunListener 发出 running 消息,告知程序已 成功运行起来了。
关于mikechen
mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。