一文带你搞懂 Spring Boot 启动原理

 2022-08-08

导言

Spring Boot 大大简化了我们的开发配置,节省了大量的时间,确实比较方便。但是对于新手来说,如果不了解个中原理,难免会遇到一些坑。

ok,废话不多说,我们进入正题:

我们所有的SringBoot 项目都会看到以下这个类:

登录后复制

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

1、启动类注解

首先,我们从注解看起,进入 @SpringBootApplication 源码可以看到,除了最基础的注解外,还增加了三个 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan
,因此将 @SpringBootApplication 替换成以上三个也具有相同的效果,这一点,我们再前面的文章中也有提到

202208082301522661.png

2、run 方法 简单说明

登录后复制

我们知道,启动类先调用了 SpringApplication 的静态方法 run,跟踪进去后发现,它会先实例化 SpringApplication,然后调用 run 方法。

202208082301545732.png

所以,要想继续分析*run*方法,我们得先了解一下 SpringApplication 方法的构造过程

3、SpringApplication 方法构造过程分析说明

我们从上述地方,进入 SpringApplication 构造方法后,如下:

202208082301559443.png

this 进入 :

202208082301574684.png

通过上述代码,我们分析到 SpringApplication 实例化时有以下几个步骤:

1). 将所有 sources 加入到全局 sources 中,目前只有一个 Application。

2). 判断 可能的web应用程序类型(WebApplicationType 是一个枚举类,包含 NONE, SERVLET, REAVTIVE 三种类型)。

202208082301589025.png

3). 设置应用程序初始化器 ApplicationContextInitializer,做一些初始化的工作。

4).设置应用程序事件监听器 ApplicationListener。

5).找出启动类,设置到 mainApplicationClass 中

202208082302001096.png

202208082302013687.png

4、run 方法 再读

回到我们进入 SpringApplication 之前的地方,再度进入run 方法

202208082302029518.png

202208082302045189.png

通过上述源码,我们可以将 run 方法执行流程分解如下:

1). 初始化 StopWatch,调用其 start 方法开始计时。
2). 调用 configureHeadlessProperty 设置系统属性 java.awt.headless,这里设置为 true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能。

2022080823020597310.png

3). 遍历 SpringApplicationRunListeners 并调用 starting 方法。

2022080823020706711.png

4). 创建一个 DefaultApplicationArguments 对象,它持有 args 参数,就是 main 函数传进来的参数调用 prepareEnvironment 方法。
5). 打印 banner。
6). 创建 Spring Boot 上下文。
7). 初始化 FailureAnalyzers。
8). 调用 prepareContext, 将上述内容加载到 上下文。
9). 调用 AbstractApplicationContext 的 refresh 方法,并注册钩子。

2022080823020820312.png

10). 在容器完成刷新后,依次调用注册的 Runners。
11). 调用 SpringApplicationRunListeners 的 finished 方法。
12). 启动完成并停止计时。
13). 初始化过程中出现异常时调用 handleRunFailure 进行处理,然后抛出 IllegalStateException 异常。

以上仅代表个人浅见,如有不正之处,还请指正,谢谢!