文章目录
4.2 SpringBoot生命周期概述
上一节了解了SpringApplication的整体设计,下面从宏观层面了解一下SpringBoot的应用从开始执行run
方法到最终退出的整个生命周期都经历了哪些重要的环节。本节是从宏观层面了解各环节,详细的原理和源码,放到后续的章节再展开。
4.2.1 创建SpringApplication
当执行SpringApplication.run
方法时,底层创建了一个SpringApplication对象,并调用其run方法:
SpringApplication.java
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
除了常规地使用SpringApplication的静态run方法,也可以自定义SpringApplication(详见 SpringBoot源码解读与原理分析(十四)SpringApplication的总体设计 。无论是何种方法,最终得到的都是一个可以调用run方法的、完整的SpringApplication对象。
在创建SpringApplication的过程中有以下关键步骤值得注意:
- Web应用类型判断:SpringBoot会根据当前应用的类路径确定当前应用最匹配的Web类型,这个Web类型会影响到实际创建的ApplicationContext落地实现类的类型;
- 初始化器&监听器的加载:在启动SpringApplication之前,它会先收集一些前期准备好的ApplicationContextInitializer以及ApplicationListener,这些组件会在启动SpringApplication的环节中发挥作用。
- 确定主启动类:SpringBoot会根据当前应用的启动状态,从方法调用栈中找到主启动类并记录下来,这个主启动类会参与默认Banner的打印。
4.2.2 启动SpringApplication
SpringApplication创建完毕后,下一步就是应用启动。整个启动逻辑非常复杂,大致可以分为8个核心步骤:
- 获取SpringApplicationRunListener监听器,该监听器会贯穿整个SpringApplication的启动流程;
- 准备运行时环境,即ApplicationContext中的Environment;
- Banner的加载与打印,默认情况下打印的Banner是以文字形式打印到控制台,可以通过定制SpringApplication来自定义配置;
- 创建ApplicationContext IOC容器,该步骤创建的依据是创建SpringApplication时推断的Web应用类型,不同的Web应用类型对应不同的ApplicationContext落地实现;
- 初始化IOC容器,该步骤会应用前面步骤准备的SpringApplicationContextnInitializer,并获取和加载配置源(默认是主启动类)。
- 刷新IOC容器,该步骤会触发SpringApplicationContext的核心refresh方法;
- 启动嵌入式Web容器,当Web应用类型不是None并且以独立运行的jar包运行SpringBoot时,底层会额外创建一个嵌入式Web容器(默认是Tomcat)并启动。
- 回调SpringBoot的运行器,包括ApplicationRunner和CommandLineRunner。
4.2.3 退出SpringApplication
当应用被关闭时,SpringBoot考虑到应用中可能会存在一些需要释放的资源,因此当SpringBoot启动成功后,内部的ApplicationContext会注册一个shutduwnhook线程。当JVM退出时,shutduwnhook线程可以确保IOC容器中的Bean能被IOC容器销毁阶段的生命周期进行回调(如被@PreDestroy注解标注的方法),从而合理地销毁IOC容器及其所有的Bean。
从源码角度,该关闭钩子的名称是固定的:
ConfigurableApplicationContext.java
String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
线程中的执行逻辑就是调用doClose方法,该方法会销毁IOC容器中所有Bean,关闭BeanFactory。
AbstractApplicationContext.java
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
// 创建钩子
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
// 线程中调用销毁IOC容器的方法
doClose();
}
}
};
// 注册钩子
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
4.3 小结
第4章到此就梳理完毕了,本章的主题是:SpringBoot的核心引导SpringApplication。回顾一下本章的梳理的内容:
(十四)SpringApplication的总体设计
(十五)SpringBoot生命周期概述
更多内容请查阅分类专栏:SpringBoot源码解读与原理分析
第5章主要梳理SpringBoot的AOP支持。主要内容包括:
- SpringFramework的AOP;
- 注解驱动AOP的核心组件。