【SpringBoot】启动配置原理-源码解析
一、启动原理
![image-20200718233338702](https://i-blog.csdnimg.cn/blog_migrate/14cf113185a5dc2107ae819d69d95a12.png)
![image-20200718233359049](https://i-blog.csdnimg.cn/blog_migrate/d5666cc407760672ec24c52f7d3fcfc1.png)
1.1 创建SpringApplication对象
SpringApplication类用于引导和启动一个Spring应用程序(即SpringBoot开发的应用)。
SpringApplication类会做如下事情启动应用:
- 为应用创建一个合适的ApplicationContext
- 注册一个CommandLinePropertySource,通过CommandLinePropertySource可以对外暴露命令行参数,并将命令行参数与spring应用中用到的properties关联起来
- 启动ApplicationContext
- 执行所有的CommandLineRunner类型bean
下面是SpringApplication类静态run方法的源码。可以看到,当我们调用这个静态run方法时,实际上会构造一个SpringApplication实例,然后再调用实例的run方法完成spring应用的启动。
下面是创建SpringApplication实例的过程
- 会保存参数中传递进来的配置类 class[]
- 会获取spring.factories 中的所有 初始化器initializer
- 会获取spring.factories 中的所有 监听者 Listeners
- 设置主配置类
![image-20200718235204396](https://i-blog.csdnimg.cn/blog_migrate/5485436c1dd8131b1106cf4118df3822.png)
initialize(sources);
private void initialize(Object[] sources) {
//保存主配置类
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断当前是否一个web应用
this.webEnvironment = deduceWebEnvironment();
//注意!这一步很重要!!
//从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
//Initializers
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//Listeners
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = deduceMainApplicationClass();
}
注意:初始化器 Initializers, run方法时你还会需要它!
// initializers 是SpringApplication的重要成员变量,在是SpringApplication实例调用run()方法时,在准备上下文环境时,就会使用加载的所有 initializers 初始化器,调用初始化方法,做一个上下文环境的准备。
private List<ApplicationContextInitializer<?>> initializers;
// listeners 也是创建实例阶段获取到应用中的重要成员,在run阶段,监听者也充当重要角色
private List<ApplicationListener<?>> listeners;
![](https://i-blog.csdnimg.cn/blog_migrate/5f52e1163260415c31ac17668517a96d.png)
1.2 run方法
public ConfigurableApplicationContext run(String... args) {
//开始的一些准备
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
// 获取所有的SpringApplicationRunListeners,从类路径下MATE-INF/springfactories 下获取所有监听者
SpringApplicationRunListeners listeners = this.getRunListeners(args);
// 监听者回调start方法开启监听
listeners.starting();
Collection exceptionReporters;
try {
// 封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
//创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//打印版本图标
Banner printedBanner = this.printBanner(environment);
// 创建ioc容器
context = this