Spring Boot应用的整个启动流程都封装在SpringApplication.run方法中,其整个流程很长,但本质上就是在Spring容器启动的基础上做了大量的扩展,按照这个思路来看看源码:
项目启动是通过SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
// 1通过SpringFactoriesLoader加载所有的SpringApplicationRunListeners,并调用starting()方法
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 2 创建并配置当前应用将要使用的Environment配置文件(profile)和属性(properties)
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
// 3 SpringBoot应用在启动输出的Banner 图
Banner printedBanner = printBanner(environment);
// 4 根据是否是web项目,来创建不同的ApplicationContext容器
context = createApplicationContext();
// 5 通过SpringFactoriesLoader创建一系列FailureAnalyzer用于监控(实现FailureAnalyzer接口的class)
analyzers = new FailureAnalyzers(context);
// 6 初始化ApplicationContext
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
// 7 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序
refreshContext(context);
// 8 查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
afterRefresh(context, applicationArguments);
// 9 执行所有SpringApplicationRunListener的finished()方法。
listeners.finished(context, null);
stopWatch.stop();
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
下面来对于上图每一步进行详细的讲解
1. 启动所有SpringApplicationRunListeners
通过SpringFactoriesLoader查找并加载所有的SpringApplicationRunListeners,通过调用starting()方法通知所有的SpringApplicationRunListeners:应用开始启动了。SpringApplicationRunListeners其本质上就是一个事件发布者,它在SpringBoot应用启动的不同时间点发布不同应用事件类型(ApplicationEvent),如果有哪些事件监听者(ApplicationListener)对这些事件感兴趣,则可以接收并且处理。
主要是启动监听器用来监听后面各个阶段的触发的事件。源码如下
public interface SpringApplicationRunListener {
// 运行run方法时立即调用此方法,可以用户非常早期的初始化工作
void starting();
// Environment准备好后,并且ApplicationContext创建之前调用
void environmentPrepared(ConfigurableEnvironment environment);
// ApplicationContext创建好后立即调用
void contextPrepared(ConfigurableApplicationContext context);
// ApplicationContext加载完成,在refresh之前调用
void contextLoaded(ConfigurableApplicationContext context);
// 当run方法结束之前调用
void finished(ConfigurableApplicationContext context, Throwable exception);
}
2. 配置Environment
创建并配置当前应用将要使用的Environment,Environment用于描述应用程序当前的运行环境,其抽象了两个方面的内容:配置文件(profile)和属性(properties),开发经验丰富的同学对这两个东西一定不会陌生:不同的环境(eg:生产环境、预发布环境)可以使用不同的配置文件,而属性则可以从配置文件、环境变量、命令行参数等来源获取。因此,当Environment准备好后,在整个应用的任何时候,都可以从Environment中获取资源。
- 判断Environment是否存在,不存在就创建(如果是web项目就创建StandardServletEnvironment,否则创建StandardEnvironment)
- 配置Environment:配置profile以及properties
- 调用SpringApplicationRunListener的environmentPrepared()方法,通知事件监听者:应用的Environment已经准备好
3. 输出Banner图
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.6.RELEASE)
4. 根据是否是web项目,来创建不同的ApplicationContext容器
5. 创建一系列FailureAnalyzer
创建流程依然是通过SpringFactoriesLoader获取到所有实现FailureAnalyzer接口的class,然后在创建对应的实例。FailureAnalyzer用于分析故障并提供相关诊断信息。
6. 初始化ApplicationContext
- 将准备好的Environment设置给ApplicationContext
- 遍历调用所有的ApplicationContextInitializer的initialize()方法来对已经创建好的ApplicationContext进行进一步的处理
- 调用SpringApplicationRunListener的contextPrepared()方法,通知所有的监听者:ApplicationContext已经准备完毕
- 将所有的bean加载到容器中
- 调用SpringApplicationRunListener的contextLoaded()方法,通知所有的监听者:ApplicationContext已经装载完毕
7 调用ApplicationContext的refresh()方法
调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序,主要获取到所有的BeanFactoryPostProcessor来对容器做一些额外的操作。BeanFactoryPostProcessor允许我们在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做一些额外的操作
// 摘自refresh()方法中一句代码
invokeBeanFactoryPostProcessors(beanFactory);
// 其实现类
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
......
}
8.查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
9.执行所有SpringApplicationRunListener的finished()方法。
这就是Spring Boot的整个启动流程,其核心就是在Spring容器初始化并启动的基础上加入各种扩展点,这些扩展点包括:ApplicationContextInitializer、ApplicationListener以及各种BeanFactoryPostProcessor等等