Springboot 启动详解

1.前言


  最近一直在看Springboot和springcloud代码,看了将近20多天,对这两个系统的认知总算是入了门。后续应该会有一个系列的文章,本文就先从Springboot的启动入手.

2.容器初始化


 Springboot 启动详解

上面的代码是Springboot的入口,现在从run方法进去

 Springboot 启动详解

点击进来后到了这里就会分成两步

1.生成一个SpringApplication对象
2.调用生成的对象的run方法

2.1】我们先看SpringApplication的构造器是如何生成一个SpringApplication对象

Springboot 启动详解

1.推断程序类型,推断规则在2.1.1

2.查找ApplicationContextInitializer的实现类,ApplicationContextInitializer是Spring框架的接口,在ApplicationContext的初始化之前,需要逐一调用ApplicationContextInitializer的实现类的initialize方法。

Springboot 启动详解

3.查找中ApplicationListener的实现类,Springboot大量的采用了事件监听机制,ApplicationListener负责将监听事件并广播出去。后续我们会详细讲解

【2.1.1】判断程序类型

Springboot 启动详解

 至此SpringApplication构造初始化就完成了。

3.容器启动


调用生成的对象的run方法

Springboot 启动详解

【3.1】记录时间

Springboot内部记录流程节点花费时间的工具类

【3.2】获取ApplicationRunListener

Springboot 启动详解

这里通过SpringApplicationRunListeners 封装了多个SpringApplicationRunListener。在容器的启动过程中,springboot将这个过程分为了五步

Springboot 启动详解

started(run方法执行的时候立马执行;对应事件的类型是ApplicationStartedEvent)
environmentPrepared(ApplicationContext创建之前并且环境信息准备好的时候调用;对应事件的类型是ApplicationEnvironmentPreparedEvent)
contextPrepared(ApplicationContext创建好并且在source加载之前调用一次;没有具体的对应事件)
contextLoaded(ApplicationContext创建并加载之后并在refresh之前调用;对应事件的类型是ApplicationPreparedEvent)
finished(run方法结束之前调用;对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent)

同时,SpringApplicationRunListener 只有一个实现类 EventPublishingRunListener,所以上述5个步骤的最终实现都会在 EventPublishingRunListener中。

我们看看start方法

Springboot 启动详解

这里的 ApplicationStartedEvent 继承 SpringApplicationEvent

Springboot 启动详解

再看publishEvent是如何把Event推送出去的

Springboot 启动详解

看到这边,发现最后发送event的还是ApplicationListener

Springboot 启动详解

这里一整套的封装,就是为了这边发送事件

Springboot 启动详解

【3.3】创建容器

 Springboot 启动详解

【3.3.1】创建Environment

Springboot 启动详解

【3.3.2】创建容器

Springboot 启动详解

【3.3.3】SpringApplication的init

 Springboot 启动详解

找到所有ApplicationContextInitializer的实现类,调用他们的initialize方法。

【3.3.4】加载mainsource到容器

 

【3.3.5】refresh,BeanFactory的设置,BeanFactoryPostProcessor接口的执行、BeanPostProcessor接口的执行、自动化配置类的解析、条件注解的解析、国际化的初始化

【3.4】容器创建之后

Springboot 启动详解

【3.4.1】Runer实现类

调用ApplicationRunner和CommandLineRunner的实现类

Springboot 启动详解

4.Springboot启动的扩展


 上述讲了springboot的启动流程,那如果我们想在启动的时候自定义一些操作,可以考虑以下几种方式。

【4.1】对容器的操作

实现  ApplicationContextInitializer 接口,重写initialize方法

Springboot 启动详解

需要注意的是,这个bean需要在META-INF/spring.factories中注册上才可以被扫描到

Springboot 启动详解 

【4.2】监听5大事件

实现 ApplicationListener

Springboot 启动详解

【4.3】实现 ApplicationRunner 或者 CommandLineRunner

Springboot 启动详解

以上,就是Springboot的启动流程,里面还有几处细节,后续会慢慢更新