Spring Boot 启动流程详解

7 阅读3分钟

一、启动流程概述

Spring Boot 的启动入口通常是 main 方法中调用 SpringApplication.run(主类, args)。整个流程分为初始化阶段(创建 SpringApplication 对象)和运行阶段(执行 run 方法)。


二、初始化阶段(创建 SpringApplication 对象)

  1. 确定 Web 应用类型
    通过检查 Classpath 中是否存在特定类(如 javax.servlet.Servletorg.springframework.web.reactive.DispatcherHandler),判断应用类型:Servlet(Spring MVC)、Reactive(WebFlux)或非 Web 应用。

  2. 加载 ApplicationContextInitializer
    利用 SpringFactoriesLoader 从所有依赖的 META-INF/spring.factories 文件中读取键为 ApplicationContextInitializer 的实现类,实例化后存入 initializers 集合。这些初始化器会在容器刷新前被调用,用于对 ApplicationContext 进行自定义设置。

  3. 加载 ApplicationListener
    同样通过 SpringFactoriesLoader 加载 ApplicationListener 实现类,存入 listeners 集合,用于监听 Spring Boot 运行过程中的各种事件。

  4. 推断主启动类
    通过分析当前线程的堆栈信息找到启动类,作为主要配置源(通常标注 @SpringBootApplication),后续会将其注册为配置类。


三、运行阶段(执行 run 方法)

  1. 启动计时器
    创建 StopWatch 对象,开始计时,用于最后输出启动耗时。

  2. 配置 headless 模式
    设置系统属性 java.awt.headless = true,适用于无显示器、键盘的服务器环境。

  3. 获取并启动 SpringApplicationRunListener
    spring.factories 加载 SpringApplicationRunListener(默认 EventPublishingRunListener),调用其 starting() 方法,发布 ApplicationStartingEvent

  4. 准备 Environment
    根据 Web 类型创建对应的 Environment(如 StandardServletEnvironment)。加载属性源:系统属性、环境变量、配置文件(application.properties/yml)。发布 ApplicationEnvironmentPreparedEvent,允许监听器(如 ConfigFileApplicationListener)进一步处理配置(如激活 profile、加载外部配置文件)。

  5. 打印 Banner
    根据配置打印 Banner(可自定义或关闭)。

  6. 创建 ApplicationContext
    根据 webApplicationType 创建对应的 ApplicationContext

    • Servlet Web:AnnotationConfigServletWebServerApplicationContext
    • Reactive Web:AnnotationConfigReactiveWebServerApplicationContext
    • 非 Web:AnnotationConfigApplicationContext
  7. 准备 ApplicationContext

    • Environment 设置到 Context。
    • 调用所有 ApplicationContextInitializerinitialize 方法。
    • 发布 ApplicationContextInitializedEvent 事件。
    • 将主启动类(作为配置类)注册到 Context。
  8. 刷新 ApplicationContext
    调用 AbstractApplicationContext.refresh(),这是 Spring 容器的核心初始化过程:

    • BeanFactory 准备:设置类加载器、表达式解析器等。
    • 执行 BeanFactoryPostProcessor:包括 ConfigurationClassPostProcessor,解析 @Configuration@ComponentScan@Import@Bean 等,将 BeanDefinition注册到容器。
    • 注册 BeanPostProcessor:拦截 Bean 实例化过程,对bean进行增加(如AOP)。
    • 初始化 MessageSource、事件广播器等:国际化
    • onRefresh 模板方法:在 ServletWebServerApplicationContext 中,此方法会创建并启动内嵌 Web 服务器(如 Tomcat、Jetty)。
    • 注册监听器
    • 实例化非懒加载的单例 Bean
    • 完成刷新,发布 ContextRefreshedEvent
  9. 刷新后置处理:finishRefresh
    空方法,留给子类扩展。

  10. 发布 ApplicationReadyEvent
    通知监听器应用已启动完成,可以处理请求。

  11. 返回 ApplicationContext
    run 方法返回初始化好的 ApplicationContext 实例。


四、启动流程图

graph TD
    A[开始: main方法调用SpringApplication.run] --> B[创建SpringApplication实例]
    
    subgraph 初始化阶段
        B --> B1[确定Web应用类型]
        B1 --> B2[加载ApplicationContextInitializer]
        B2 --> B3[加载ApplicationListener]
        B3 --> B4[推断主启动类]
    end

    B4 --> C[调用run方法]

    subgraph 运行阶段
        C --> D[启动StopWatch计时器]
        D --> E[配置java.awt.headless]
        E --> F[获取并启动SpringApplicationRunListeners<br>发布ApplicationStartingEvent]
        F --> G[准备Environment<br>加载配置属性]
        G --> H[打印Banner]
        H --> I[创建ApplicationContext]
        I --> J[准备ApplicationContext<br>应用Initializer]
        J --> K[刷新Context<br>调用refresh方法]
        
        subgraph refresh方法内部
            K --> K1[BeanFactory准备]
            K1 --> K2[执行BeanFactoryPostProcessor<br>解析配置类]
            K2 --> K3[注册BeanPostProcessor]
            K3 --> K4[初始化MessageSource等]
            K4 --> K5[onRefresh<br>启动内嵌Web服务器]
            K5 --> K6[注册监听器]
            K6 --> K7[初始化剩余单例Bean]
            K7 --> K8[完成刷新<br>发布ContextRefreshedEvent]
        end

        K8 --> L[刷新后置处理]
        L --> M[发布ApplicationReadyEvent]
        M --> N[返回ApplicationContext]
    end

    N --> O[启动完成]