Spring Boot 启动全解析:4 大关键动作 + 底层逻辑

2 阅读5分钟

Spring Boot 以 “约定优于配置” 的核心思想大幅简化了 Spring 应用的开发与部署,其启动流程是理解框架底层原理的关键。本文将从 “核心动作” 和 “实现细节” 两个维度,全面拆解 Spring Boot 启动过程中完成的核心工作及底层实现逻辑。

一、Spring Boot 启动流程核心动作

Spring Boot 启动的本质是完成 “环境准备 - 容器初始化 - 服务启动” 的全链路流程,核心可拆解为以下 4 个关键动作,且各动作遵循严格的执行顺序:

  1. 加载配置文件:整合多来源配置(内置默认、自定义配置文件、环境变量、命令行参数等),构建统一的应用环境上下文;
  2. 加载日志组件:初始化日志系统,确保启动过程及应用运行的日志可追溯、可配置;
  3. 创建 Spring 容器并初始化 Bean:构建 IoC 容器,扫描指定范围的 Bean 定义、解析注解、完成 Bean 的实例化与依赖注入;
  4. 启动嵌入式 Web 服务器(如 Tomcat):针对 Web 应用,初始化嵌入式服务器并绑定 Servlet/Filter 等组件,对外提供服务。

二、核心动作的底层实现细节

2.1 加载配置文件:整合多来源配置,构建环境上下文

Spring Boot 配置文件的加载核心依赖 ConfigFileApplicationListener(Spring Boot 2.4+ 后逐步被 ConfigDataEnvironmentPostProcessor 替代,但核心逻辑一致),其核心作用是扫描指定路径下的配置文件(如 application.yml/application.properties),并将配置项整合到 Environment 上下文对象中。

调用流程

%%{init:"wrap": false, {"flowchart":{"wrappingWidth":2000}}}%%
graph TD
A("SpringApplication.run() 入口方法")-->|创建 SpringApplication 实例| B("new SpringApplication(primarySources)")
B-->|构造函数初始化监听器| C("setListeners(getSpringFactoriesInstances(ApplicationListener.class))<br/>核心逻辑:读取 META-INF/spring.factories 文件,加载所有<br/> ApplicationListener 实现类,包含 ConfigFileApplicationListener")
C -->D("调用 application.run(args) 执行启动流程")
D -->|初始化运行监听器| E("SpringApplicationRunListeners listeners = getRunListeners(args)<br/>读取 META-INF/spring.factories 加载 EventPublishingRunListener<br/>(事件发布监听器)")
E-->|准备环境上下文| F("prepareEnvironment(listeners, applicationArguments)")
F-->|发布环境准备事件|G("listeners.environmentPrepared(environment)")
G-->|事件分发|H("EventPublishingRunListener.environmentPrepared()<br/>触发 EnvironmentPreparedEvent 事件")
H-->|监听器处理事件|I("ConfigFileApplicationListener.onApplicationEvent(EnvironmentPreparedEvent)")
I-->|核心处理逻辑|J("onApplicationEnvironmentPreparedEvent(EnvironmentPreparedEvent)")
J-->|解析配置文件|K("postProcessEnvironment(environment, applicationArguments)<br/>1. 扫描 classpath:/、classpath:/config/、file:./、file:./config/ 等路径;<br/>2. 按优先级加载 application.properties/yml、profile 专属配置;<br/>3. 整合环境变量、命令行参数覆盖配置项;<br/>4. 将配置项注入 Environment 上下文")


classDef leftAlign text-align:left;
class A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,S,Y,Z leftAlign;

关键补充说明

  • 配置加载优先级:命令行参数 > 环境变量 > 自定义配置文件(如 application-dev.yml)> 内置默认配置;
  • 支持的配置格式:properties、yml、yaml,且支持多环境隔离(通过 spring.profiles.active 指定激活的 profile);
  • 核心目的:将分散的配置统一整合到 Environment 对象中,后续 Bean 初始化、服务器启动均可通过 Environment 获取配置项(如 server.port)。

2.2 加载日志组件:初始化日志系统,保障日志可配置

Spring Boot 启动时优先初始化日志组件,核心依赖 LoggingApplicationListener,其作用是根据应用配置(或默认规则)选择并初始化日志框架(如 Logback、Log4j2、Java Util Logging),确保启动过程的日志能正常输出。

调用流程

%%{init:"wrap": false, {"flowchart":{"wrappingWidth":2000}}}%%
graph TD
A("SpringApplication.run() 入口方法")-->|创建 SpringApplication 实例| B("new SpringApplication(primarySources)")
B-->|构造函数初始化监听器| C("setListeners(getSpringFactoriesInstances(ApplicationListener.class))<br/>读取 META-INF/spring.factories 加载 LoggingApplicationListener")
C -->D("调用 application.run(args) 执行启动流程")
D -->|初始化运行监听器| E("SpringApplicationRunListeners listeners = getRunListeners(args)<br/>加载 EventPublishingRunListener")
E-->|发布应用环境已准备事件|G("listeners.environmentPrepared()<br/>触发ApplicationEnvironmentPreparedEvent 事件")
G-->|事件分发|H("EventPublishingRunListener.environmentPrepared()")
H-->|监听器处理事件|I("LoggingApplicationListener.onApplicationEvent(ApplicationEvent)")
I-->|核心处理逻辑|J("onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent)")
J-->|选择并初始化日志系统|K("LoggingSystem.get(classLoader)<br/>1. 按优先级检测日志框架(Logback > Log4j2 > JUL);<br/>2. 加载日志配置文件(如 logback-spring.xml);<br/>3. 初始化日志级别、输出格式、输出路径等;<br/>4. 绑定日志系统到 Spring 环境,支持运行时动态调整")


classDef leftAlign text-align:left;
class A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,S,Y,Z leftAlign;

关键补充说明

  • 日志框架优先级:Spring Boot 默认内置 Logback(无需额外依赖),若需切换为 Log4j2,需排除 Logback 依赖并引入 Log4j2 相关包;
  • 日志配置加载路径:默认扫描 classpath:logback-spring.xmlclasspath:log4j2.xml 等,也可通过 logging.config 配置项指定自定义路径;
  • 核心目的:在应用核心逻辑启动前完成日志初始化,避免启动过程中日志丢失或格式异常。

2.3 创建 Spring 容器并初始化 Bean:构建 IoC 核心,管理 Bean 生命周期

Spring Boot 核心是构建 Spring IoC 容器,核心依赖 ConfigurationClassPostProcessor(Bean 定义后置处理器),其作用是解析启动类上的注解(如 @SpringBootApplication)、扫描指定包下的 Bean、解析自动配置类,最终完成 Bean 的注册与初始化。

调用流程

%%{init:"wrap": false, {"flowchart":{"wrappingWidth":2000}}}%%
graph TD
A("SpringApplication.run() 入口方法")-->|"创建 SpringApplication 实例"| A1("new SpringApplication(primarySources)")
A1-->|执行启动逻辑| A2("application.run(args)")
A2-->|创建应用上下文| B("createApplicationContext()<br/>根据应用类型选择上下文:Web 应用为 AnnotationConfigServletWebServerApplicationContext,<br/>非 Web 应用为 AnnotationConfigApplicationContext")
B-->|"初始化 Web 应用上下文"| C("context = new AnnotationConfigServletWebServerApplicationContext()")
C -->|"初始化 Bean 定义读取器"| D("new AnnotatedBeanDefinitionReader(beanFactory)<br/>用于解析注解驱动的 Bean 定义")
D -->|注册核心后置处理器| E("AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)<br/>向容器中注册 ConfigurationClassPostProcessor 等核心处理器")
E-->|关键处理器注册完成|F("ConfigurationClassPostProcessor 加入容器(Bean 定义解析核心)")
F-->|"注册启动类为 Bean"|C1("application.load(primarySources)<br/>将 @SpringBootApplication 标注的启动类作为核心 Bean 注入容器")
C1-->|"刷新上下文(核心步骤)"|G("refreshContext(context)")
G-->|容器刷新核心方法|H("context.refresh()<br/>执行 Spring 容器初始化全流程")
H-->|"执行 BeanFactory 后置处理器"|I("invokeBeanFactoryPostProcessors(beanFactory)")
I-->|分发后置处理器执行逻辑|J("PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()")
J-->|"执行 BeanDefinitionRegistry 后置处理器"|K("invokeBeanDefinitionRegistryPostProcessors(registryProcessors, registry)")
K-->|"解析并注册 Bean 定义"|L("ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(registry)<br/>1. 解析启动类上的 @ComponentScan,扫描指定包下的 @Component/@Service/@Repository 等 Bean;<br/>2. 解析 @EnableAutoConfiguration,读取 META-INF/spring/<br/>org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,加载自动配置类;<br/>3. 解析 @Bean 注解,注册手动声明的 Bean;<br/>4. 将所有 Bean 定义注册到 IoC 容器")
L-->|"Bean 实例化与依赖注入"|M("finishBeanFactoryInitialization(beanFactory)<br/>实例化所有非懒加载 Bean,完成依赖注入、初始化方法(@PostConstruct)执行")

classDef leftAlign text-align:left;
class A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,S,Y,Z leftAlign;

关键补充说明

  • 自动配置核心:@EnableAutoConfiguration 是自动配置的入口,Spring Boot 通过 spring-boot-autoconfigure 包中的自动配置类,实现 “按需加载”(如引入 redis 依赖则自动配置 RedisTemplate);
  • 扫描范围:默认扫描启动类所在包及其子包,可通过 @ComponentScan 指定自定义扫描范围;
  • 核心目的:构建完整的 IoC 容器,管理所有 Bean 的生命周期,为应用提供依赖注入、AOP 等核心能力。

2.4 启动嵌入式 Tomcat:初始化 Web 服务器,对外提供服务

对于 Web 应用(引入 spring-boot-starter-web),Spring Boot 会自动启动嵌入式 Tomcat(默认),核心逻辑在 ServletWebServerApplicationContextonRefresh 方法中,完成服务器创建、Servlet/Filter 绑定、端口监听等操作。

调用流程

%%{init:"wrap": false, {"flowchart":{"wrappingWidth":2000}}}%%
graph TD
A("SpringApplication.run() 入口方法")-->|创建 SpringApplication 实例| A1("new SpringApplication(primarySources)")
A1-->|执行启动逻辑| A2("application.run(args)")
A2-->|创建应用上下文| B("createApplicationContext()")
B-->|初始化 Web 应用上下文| C("context = new AnnotationConfigServletWebServerApplicationContext()")
C-->|刷新上下文|G("refreshContext(context)")
G-->|容器刷新核心方法|H("context.refresh()")
H-->|Web 服务器初始化|I("onRefresh()<br/>ServletWebServerApplicationContext 重写的刷新方法,专用于 Web 服务器启动")
I-->|创建 Tomcat 实例|J("createWebServer()<br/>1. 根据 server.port 等配置创建 Tomcat 实例;<br/>2. 配置 Tomcat 基础路径、连接器(Connector)、引擎(Engine)等核心组件;<br/>3. 绑定上下文路径(server.servlet.context-path)")
J-->|绑定 Servlet/Filter 等组件|L("getSelfInitializer()<br/>1. 从 IoC 容器中获取所有 ServletContextInitializer 实现类(如 DispatcherServletRegistrationBean);<br/>2. 扫描容器中的 @Servlet/@Filter 注解组件,封装为 ServletContextInitializer 实现类;<br/>3. Tomcat 创建 ServletContext 时,执行这些 Initializer,完成 DispatcherServlet、Filter 等组件的注册")
L-->|启动 Tomcat 服务器|K("finishRefresh()<br/>1. 调用 Tomcat.start() 启动服务器;<br/>2. 绑定端口监听,等待客户端请求;<br/>3. 发布 ApplicationStartedEvent 事件,标识应用启动完成")


classDef leftAlign text-align:left;
class A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,S,Y,Z leftAlign;

关键补充说明

  • 服务器切换:若需将 Tomcat 替换为 Jetty/Undertow,只需排除 spring-boot-starter-tomcat 依赖,引入 spring-boot-starter-jetty/spring-boot-starter-undertow
  • 核心组件:DispatcherServlet 是 Spring MVC 的核心 Servlet,由 DispatcherServletAutoConfiguration 自动配置,负责接收并分发所有 Web 请求;
  • 端口配置:默认端口 8080,可通过 server.port 配置,若配置为 0 则随机分配端口;
  • 核心目的:启动嵌入式 Web 服务器,将 Spring MVC 核心组件绑定到服务器,对外提供 HTTP 服务。

三、启动流程整体时序总结

Spring Boot 启动流程的核心时序可概括为:

SpringApplication.run()
→ 初始化监听器(加载 LoggingApplicationListener/ConfigFileApplicationListener)
→ 发布 ApplicationStartingEvent(初始化日志)
→ 准备环境(加载配置文件,构建 Environment)
→ 创建 IoC 容器(AnnotationConfigServletWebServerApplicationContext)
→ 注册 ConfigurationClassPostProcessor(解析 Bean 定义)
→ 刷新容器(refresh())
 → 执行 BeanFactory 后置处理器(扫描并注册 Bean)
 → 实例化 Bean(完成依赖注入)
 → 初始化 Web 服务器(创建并启动 Tomcat)
→ 发布 ApplicationStartedEvent(启动完成)

四、核心总结

Spring Boot 启动流程的本质是 “通过监听器机制完成环境准备,通过后置处理器完成 Bean 容器初始化,通过 Web 应用上下文完成嵌入式服务器启动”,其核心优势在于:

  1. 自动化:通过 spring.factories/ 自动配置类,实现 “按需加载”,无需手动配置核心组件;
  2. 标准化:固定的启动流程确保应用开发的一致性,降低配置成本;
  3. 可扩展:通过自定义 ApplicationListener/EnvironmentPostProcessor/BeanFactoryPostProcessor,可灵活扩展启动逻辑。 理解上述流程,不仅能帮助开发者定位启动过程中的异常(如配置加载失败、Bean 冲突、端口占用),也能为自定义 Spring Boot Starter、扩展框架能力提供底层支撑。