侧边栏壁纸
博主头像
牧云

怀璧慎显,博识谨言。

  • 累计撰写 198 篇文章
  • 累计创建 19 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

SpringBoot 启动流程

秋之牧云
2026-05-14 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

1. 概述

SpringBoot 的启动流程并非黑盒,其核心逻辑可以高度概括为两个主要阶段:初始化阶段(构建 SpringApplication 实例)与 运行阶段(执行 run 方法并刷新容器)。理解这一流程有助于排查启动错误、优化启动速度以及进行自定义扩展。

2. 阶段一:初始化 (Initialization)

在调用 SpringApplication.run() 之前或初期,系统会创建一个 SpringApplication 对象。此阶段主要完成“环境摸底”和“组件预备”,尚未创建 IoC 容器

  • 推断应用类型:检查 Classpath 中是否存在 Servlet 或 Reactive 相关类,判断应用是 Standard、Servlet Web 还是 Reactive Web 类型 。
  • 加载核心组件:利用 SPI 机制(读取 META-INF/spring.factoriesorg.springframework.boot.autoconfigure.AutoConfiguration.imports),加载 ApplicationContextInitializerApplicationListener。这些组件将在后续生命周期中发挥作用 。
  • 确定主类:通过栈跟踪信息推断出包含 main 方法的类,作为配置源的根节点。

3. 阶段二:运行 (Execution)

执行 application.run(args) 方法,这是启动的主战场,主要包含以下关键步骤:

3.1 前置准备

  1. 启动监听:获取 SpringApplicationRunListeners 并广播“正在启动”事件,同时开启计时器 。
  2. 准备环境 (Prepare Environment):创建并配置 Environment 对象。此时会加载系统属性、环境变量、命令行参数以及 application.yml/properties 配置文件 。
  3. 打印 Banner:在控制台输出 SpringBoot 的标志性图案(可自定义或关闭)。

3.2 容器构建与刷新 (核心)

  1. 创建上下文 (Create Context):根据第一阶段推断的应用类型,实例化具体的 ApplicationContext(如 AnnotationConfigServletWebServerApplicationContext)。
  2. 准备上下文 (Prepare Context):将准备好的 Environment 注入容器,应用之前加载的 Initializer,并将主启动类注册为 BeanDefinition。
  3. 刷新上下文 (Refresh Context)这是最核心的步骤,委托给 Spring Framework 的标准 refresh() 流程:
    • Bean 工厂预处理:准备 BeanFactory。
    • 自动配置:解析 @EnableAutoConfiguration,根据条件注解(@Conditional)加载自动配置类,实例化所有非懒加载的单例 Bean 。
    • 启动内嵌容器:如果是 Web 应用,在此阶段启动内嵌的 Tomcat、Jetty 或 Undertow 服务器,并监听端口。

3.3 收尾工作

  1. 刷新后处理:停止计时器,记录启动耗时日志。
  2. 执行 Runner:查找容器中所有实现了 CommandLineRunnerApplicationRunner 接口的 Bean,并按顺序执行其 run 方法。这为开发者提供了在应用完全启动后执行初始化逻辑的标准入口 。
  3. 完成启动:广播 ApplicationReadyEvent 事件,返回 ApplicationContext 实例,应用正式对外提供服务。

4. 启动流程可视化

以下 Mermaid 流程图清晰展示了从初始化到运行结束的核心路径:

graph TD
    Start([开始: SpringApplication.run]) --> Init[阶段一: 初始化 SpringApplication]
    
    subgraph InitPhase [初始化阶段]
        Init --> InferType[1. 推断应用类型<br/>Web/Reactive/None]
        InferType --> LoadComponents[2. 加载初始化器与监听器<br/>SPI机制读取 spring.factories]
        LoadComponents --> FindMain[3. 推断主启动类]
    end

    FindMain --> Run[阶段二: 执行 run 方法]

    subgraph RunPhase [运行阶段]
        Run --> ListenersStart[4. 启动监听器 & 开启计时]
        ListenersStart --> PrepEnv[5. 准备环境 Environment<br/>加载配置文件/环境变量]
        PrepEnv --> PrintBanner[6. 打印 Banner]
        PrintBanner --> CreateContext[7. 创建 ApplicationContext<br/>IoC 容器实例化]
        CreateContext --> PrepContext[8. 准备上下文<br/>注入环境/应用初始化器]
        PrepContext --> Refresh[9. 刷新上下文 Refresh<br/>核心步骤]
        
        subgraph RefreshCore [Refresh 内部关键动作]
            Refresh --> AutoConfig[9.1 自动配置 & Bean 装配]
            AutoConfig --> StartServer[9.2 启动内嵌 Web 服务器<br/>Tomcat/Jetty等]
        end
        
        StartServer --> AfterRefresh[10. 刷新后处理]
        AfterRefresh --> RunRunners[11. 执行 CommandLineRunner/<br/>ApplicationRunner]
        RunRunners --> Finish[12. 广播启动完成事件 & 返回上下文]
    end

    Finish --> End([结束: 应用就绪])

    style InitPhase fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style RunPhase fill:#fff3e0,stroke:#e65100,stroke-width:2px
    style RefreshCore fill:#f3e5f5,stroke:#4a148c,stroke-width:2px,stroke-dasharray: 5 5
    style Refresh fill:#ffccbc,stroke:#bf360c,stroke-width:2px

图解说明:

  • 蓝色区域(初始化阶段):主要做准备工作,确定“是什么应用”以及“有哪些组件可用”,此时尚未创建 IoC 容器。
  • 橙色区域(运行阶段):真正的启动过程,核心是构建和刷新 IoC 容器。
  • 紫色虚线框(Refresh 核心):这是最耗时的部分,Spring 在此处完成所有 Bean 的创建、依赖注入以及内嵌服务器的启动。
  • 流程走向:从上至下,线性执行,其中 Refresh Context 是最关键的转折点,标志着 Spring 容器正式可用。

5. 关键总结

  • SPI 机制是关键:SpringBoot 的扩展性(如自动配置、监听器加载)高度依赖于 SPI 机制读取配置文件。
  • Refresh 是重心:绝大部分启动时间消耗在 refresh() 阶段,特别是 Bean 的扫描、创建和内嵌服务器的启动。
  • 扩展点清晰
    • 若需在环境准备前干预:使用 SpringApplicationRunListener
    • 若需在容器刷新前干预:使用 ApplicationContextInitializer
    • 若需在启动完成后执行业务逻辑:使用 CommandLineRunner / ApplicationRunner

6. 参考流程图逻辑

[开始] 
  ↓
[推断类型 / 加载SPI组件] 
  ↓
[准备 Environment] 
  ↓
[创建 Context] 
  ↓
[Refresh: 自动配置 + 启动Tomcat] 
  ↓
[执行 Runners] 
  ↓
[结束]

注:本笔记基于 SpringBoot 通用启动机制整理,具体细节可能因版本(2.x vs 3.x)略有差异,但核心脉络保持一致。

0

评论区