基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Spring Boot应用的启动流程

知识点图片

揭秘Spring Boot启动流程:核心是SpringApplication.run()创建并刷新ApplicationContext,利用自动配置机制,完成Bean创建及内嵌服务器启动。

我们来详细、分步地解析一下 Spring Boot 应用的启动流程。

Spring Boot 的启动流程核心目标是:创建并配置 Spring 的 ApplicationContext (应用上下文)。这个过程被 SpringApplication.run() 方法高度封装,它自动化了大量原本需要手动配置的工作。

整个流程可以分为三大阶段:

  1. SpringApplication 对象的初始化阶段:准备启动所需的基础环境。
  2. run() 方法执行阶段:这是启动的核心,包括创建环境、创建 ApplicationContext、执行刷新等。
  3. ApplicationContext 刷新阶段:这是经典的 Spring IoC 容器启动过程,也是 Bean 创建和装配的核心。

下面我们来详细分解这个过程。


零、起点:main 方法

一切都始于一个标准的 Java main 方法。

java
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
  • @SpringBootApplication: 这是一个复合注解,是启动流程的第一个关键配置。它包含了:
    • @SpringBootConfiguration: 继承自 @Configuration,表明这个类是一个 Spring 配置类。
    • @EnableAutoConfiguration: 启动自动配置的核心。它会告诉 Spring Boot 根据 classpath 中的依赖,自动配置项目。
    • @ComponentScan: 自动扫描该类所在包及其子包下的 Spring 组件(如 @Component, @Service, @RestController 等)。
  • SpringApplication.run(...): 这是整个启动流程的入口,所有魔法都从这里开始。

一、SpringApplication 对象的初始化阶段

当我们调用 SpringApplication.run(MyApplication.class, args) 时,它内部首先会创建一个 SpringApplication 实例。在这个构造函数中,它会做以下几件重要的事情:

  1. 推断应用类型:通过检查 classpath,判断当前是哪种类型的应用。
    • REACTIVE: 如果存在 spring-webflux
    • SERVLET: 如果存在 spring-webmvc (这是最常见的)。
    • NONE: 非 Web 应用。
  2. 加载 Initializers 和 Listeners:使用 Spring 的 SPI (Service Provider Interface) 机制,从 META-INF/spring.factories 文件中加载 ApplicationContextInitializerApplicationListener 接口的实现类。这些类会在启动过程中的特定时间点被回调,允许我们进行自定义扩展。
  3. 推断主应用类 (Main Class):通过分析堆栈信息,找出包含 main 方法的类,即 MyApplication.class

至此,一个配置了基本信息的 SpringApplication 对象准备就绪。


二、run() 方法执行阶段

这是启动流程的核心和主干。

  1. 创建并启动 StopWatch:用于记录启动耗时。
  2. 创建并配置 Environment (环境)
    • 创建一个 ConfigurableEnvironment 对象。
    • 加载和整合各种配置源,形成一个统一的配置视图。加载顺序有优先级,后面的会覆盖前面的:
      • 命令行参数 (--server.port=9090)
      • JVM 系统属性 (-D...)
      • 操作系统环境变量
      • application-{profile}.properties.yml 文件
      • application.properties.yml 文件
      • @PropertySource 注解指定的配置
      • 默认属性
  3. 打印 Banner:在控制台输出 Spring Boot 的横幅,你可以在 src/main/resources 下创建 banner.txt 文件来定制它。
  4. 创建 ApplicationContext (应用上下文)
    • 根据之前推断的应用类型,创建相应的 ApplicationContext 实例。
    • 对于 Web 应用,通常是 AnnotationConfigServletWebServerApplicationContext
    • 对于响应式应用,是 AnnotationConfigReactiveWebServerApplicationContext
  5. 预处理 ApplicationContext (prepareContext)
    • 将之前创建的 Environment 设置到 ApplicationContext 中。
    • 调用之前加载的 ApplicationContextInitializerinitialize 方法,对 ApplicationContext 进行进一步的配置。
    • 加载所有的 Bean 定义(BeanDefinition),包括主配置类和你自己定义的 Bean。此时 Bean 还没有被实例化。
  6. 刷新 ApplicationContext (refreshContext)
    • 这是整个启动流程中最核心、最复杂的一步。它会触发 Spring 容器的刷新机制,完成所有 Bean 的创建、依赖注入和初始化。我们将在下一节详细讲解。
  7. 刷新后处理 (afterRefresh):提供一个空的模板方法,用于子类扩展。
  8. 调用 Runner
    • ApplicationContext 完全准备好之后,Spring Boot 会查找所有实现了 ApplicationRunnerCommandLineRunner 接口的 Bean。
    • 按照 @Order 注解或 Ordered 接口定义的顺序,依次调用它们的 run 方法。这通常用于执行一些应用启动后需要立即运行的任务(如数据初始化、启动定时任务等)。
  9. 应用就绪:至此,应用已成功启动,并准备好接收请求。run 方法返回 ConfigurableApplicationContext 实例。

三、ApplicationContext 刷新阶段 (refreshContext)

这一步实际上是调用了 Spring 框架自身的 AbstractApplicationContext.refresh() 方法。它是 Spring IoC 容器生命周期的核心。其中与 Spring Boot 启动最相关的步骤是:

  1. invokeBeanFactoryPostProcessors (调用 BeanFactory 后置处理器)

    • 自动配置的魔法发生在这里!
    • @EnableAutoConfiguration 注解通过 @Import(AutoConfigurationImportSelector.class) 导入了 AutoConfigurationImportSelector
    • 这个 Selector 会去扫描所有依赖 JAR 包中的 META-INF/spring.factories (或 Spring Boot 3+ 的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports) 文件。
    • 它会加载文件中列出的所有自动配置类 (例如 DataSourceAutoConfiguration, WebMvcAutoConfiguration 等)。
    • 这些自动配置类本身都是 @Configuration 配置类,它们内部使用了大量的 @Conditional 注解(如 @ConditionalOnClass, @ConditionalOnBean, @ConditionalOnProperty)。
    • Spring Boot 会根据当前的环境(比如 classpath 中是否存在某个类、是否已存在某个 Bean、配置文件中是否有某个属性)来判断这些自动配置类是否生效。
    • 如果生效,这些配置类中定义的 Bean 就会被注册到 ApplicationContext 中。例如,如果 classpath 中有 tomcat-embed-core.jar 并且没有用户自定义的 TomcatServletWebServerFactory Bean,那么 ServletWebServerFactoryAutoConfiguration 就会生效,并创建一个 Tomcat 服务器的 Bean。
  2. registerBeanPostProcessors (注册 Bean 后置处理器):注册所有 BeanPostProcessor,它们可以在 Bean 初始化前后进行干预。

  3. onRefresh (刷新)

    • 对于 Web 应用,在这一步会创建并启动内嵌的 Web 服务器(如 Tomcat, Jetty, Undertow)。服务器会开始监听指定的端口。
  4. finishBeanFactoryInitialization (完成 BeanFactory 初始化)

    • 实例化所有剩余的非懒加载单例 Bean
    • 这个过程会进行依赖注入(@Autowired)、属性填充、执行初始化方法(如 @PostConstruct, afterPropertiesSet)等。
  5. finishRefresh (完成刷新)

    • 发布 ContextRefreshedEvent 事件,通知所有监听器容器已经刷新完毕。

总结 & 流程图

一图胜千言,简化版流程图:

plaintext
main() 方法
    │
    └──> SpringApplication.run()
            │
            ├─ 1. 创建 SpringApplication 实例 (推断应用类型, 加载 SPI 扩展)
            │
            ├─ 2. run() 方法执行
            │   ├── 准备 Environment (加载 application.properties 等配置)
            │   ├── 打印 Banner
            │   ├── 创建 ApplicationContext (例如: AnnotationConfigServletWebServerApplicationContext)
            │   ├── prepareContext (准备上下文, 加载 BeanDefinition)
            │   │
            │   └── refreshContext (刷新上下文)  <-- 核心
            │       ├── invokeBeanFactoryPostProcessors()  <-- 自动配置在这里生效
            │       │   (加载 META-INF/spring.factories 中的自动配置类, 并根据 @Conditional 判断是否生效)
            │       │
            │       ├── onRefresh()  <-- 启动内嵌 Tomcat/Jetty 等 Web 服务器
            │       │
            │       └── finishBeanFactoryInitialization()  <-- 实例化所有单例 Bean, 完成依赖注入
            │
            ├─ 3. 调用 ApplicationRunner 和 CommandLineRunner
            │
            └──> 应用启动完成,可以处理请求

总而言之,Spring Boot 的启动流程是一个高度自动化和可扩展的过程。它以 SpringApplication.run() 为核心,通过自动配置机制,智能地根据项目依赖和用户配置来组装一个功能完备的 Spring 应用,极大地简化了开发者的工作。

00:00
00:00