Spring Boot 以 "约定优于配置" 的核心思想大幅简化了 Spring 应用的开发与部署,其启动流程是理解框架底层原理的关键。本文将从 "核心动作" 和 "实现细节" 两个维度,全面拆解 Spring Boot 启动过程中完成的核心工作及底层实现逻辑。
一、Spring Boot 启动流程核心动作
Spring Boot 启动的本质是完成 "环境准备 - 容器初始化 - 服务启动" 的全链路流程,核心可拆解为以下 4 个关键动作,且各动作遵循严格的执行顺序:
- 加载配置文件:整合多来源配置(内置默认、自定义配置文件、环境变量、命令行参数等),构建统一的应用环境上下文;
- 加载日志组件:初始化日志系统,确保启动过程及应用运行的日志可追溯、可配置;
- 创建 Spring 容器并初始化 Bean:构建 IoC 容器,扫描指定范围的 Bean 定义、解析注解、完成 Bean 的实例化与依赖注入;
- 启动嵌入式 Web 服务器(如 Tomcat):针对 Web 应用,初始化嵌入式服务器并绑定 Servlet/Filter 等组件,对外提供服务。
二、核心动作的底层实现细节
2.1 加载配置文件:整合多来源配置,构建环境上下文
Spring Boot 配置文件的加载核心依赖 ConfigFileApplicationListener(Spring Boot 2.4+ 后逐步被 ConfigDataEnvironmentPostProcessor 替代,但核心逻辑一致),其核心作用是扫描指定路径下的配置文件(如 application.yml/application.properties),并将配置项整合到 Environment 上下文对象中。
调用流程
创建 SpringApplication 实例 构造函数初始化监听器 初始化运行监听器 准备环境上下文 发布环境准备事件 事件分发 监听器处理事件 核心处理逻辑 解析配置文件 SpringApplication.run() 入口方法 new SpringApplication(primarySources) setListeners(getSpringFactoriesInstances(ApplicationListener.class))
核心逻辑:读取 META-INF/spring.factories 文件,加载所有
ApplicationListener 实现类,包含 ConfigFileApplicationListener 调用 application.run(args) 执行启动流程 SpringApplicationRunListeners listeners = getRunListeners(args)
读取 META-INF/spring.factories 加载 EventPublishingRunListener
(事件发布监听器) prepareEnvironment(listeners, applicationArguments) listeners.environmentPrepared(environment) EventPublishingRunListener.environmentPrepared()
触发 EnvironmentPreparedEvent 事件 ConfigFileApplicationListener.onApplicationEvent(EnvironmentPreparedEvent) onApplicationEnvironmentPreparedEvent(EnvironmentPreparedEvent) postProcessEnvironment(environment, applicationArguments)
- 扫描 classpath:/、classpath:/config/、file:./、file:./config/ 等路径;
- 按优先级加载 application.properties/yml、profile 专属配置;
- 整合环境变量、命令行参数覆盖配置项;
- 将配置项注入 Environment 上下文
关键补充说明
- 配置加载优先级:命令行参数 > 环境变量 > 自定义配置文件(如 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),确保启动过程的日志能正常输出。
调用流程
创建 SpringApplication 实例 构造函数初始化监听器 初始化运行监听器 发布应用启动事件 事件分发 监听器处理事件 核心处理逻辑 选择并初始化日志系统 SpringApplication.run() 入口方法 new SpringApplication(primarySources) setListeners(getSpringFactoriesInstances(ApplicationListener.class))
读取 META-INF/spring.factories 加载 LoggingApplicationListener 调用 application.run(args) 执行启动流程 SpringApplicationRunListeners listeners = getRunListeners(args)
加载 EventPublishingRunListener listeners.starting()
触发 ApplicationStartingEvent 事件 EventPublishingRunListener.starting() LoggingApplicationListener.onApplicationEvent(ApplicationStartingEvent) onApplicationStartingEvent(ApplicationStartingEvent) LoggingSystem.get(classLoader)
- 按优先级检测日志框架(Logback > Log4j2 > JUL);
- 加载日志配置文件(如 logback-spring.xml);
- 初始化日志级别、输出格式、输出路径等;
- 绑定日志系统到 Spring 环境,支持运行时动态调整
关键补充说明
- 日志框架优先级:Spring Boot 默认内置 Logback(无需额外依赖),若需切换为 Log4j2,需排除 Logback 依赖并引入 Log4j2 相关包;
- 日志配置加载路径:默认扫描
classpath:logback-spring.xml、classpath:log4j2.xml等,也可通过logging.config配置项指定自定义路径; - 核心目的:在应用核心逻辑启动前完成日志初始化,避免启动过程中日志丢失或格式异常。
2.3 创建 Spring 容器并初始化 Bean:构建 IoC 核心,管理 Bean 生命周期
Spring Boot 核心是构建 Spring IoC 容器,核心依赖 ConfigurationClassPostProcessor(Bean 定义后置处理器),其作用是解析启动类上的注解(如 @SpringBootApplication)、扫描指定包下的 Bean、解析自动配置类,最终完成 Bean 的注册与初始化。
调用流程
创建 SpringApplication 实例 执行启动逻辑 创建应用上下文 初始化 Web 应用上下文 初始化 Bean 定义读取器 注册核心后置处理器 关键处理器注册完成 注册启动类为 Bean 刷新上下文(核心步骤) 容器刷新核心方法 执行 BeanFactory 后置处理器 分发后置处理器执行逻辑 执行 BeanDefinitionRegistry 后置处理器 解析并注册 Bean 定义 Bean 实例化与依赖注入 SpringApplication.run() 入口方法 new SpringApplication(primarySources) application.run(args) createApplicationContext()
根据应用类型选择上下文:Web 应用为 AnnotationConfigServletWebServerApplicationContext,
非 Web 应用为 AnnotationConfigApplicationContext context = new AnnotationConfigServletWebServerApplicationContext() new AnnotatedBeanDefinitionReader(beanFactory)
用于解析注解驱动的 Bean 定义 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)
向容器中注册 ConfigurationClassPostProcessor 等核心处理器 ConfigurationClassPostProcessor 加入容器(Bean 定义解析核心) application.load(primarySources)
将 @SpringBootApplication 标注的启动类作为核心 Bean 注入容器 refreshContext(context) context.refresh()
执行 Spring 容器初始化全流程 invokeBeanFactoryPostProcessors(beanFactory) PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() invokeBeanDefinitionRegistryPostProcessors(registryProcessors, registry) ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(registry)
- 解析启动类上的 @ComponentScan,扫描指定包下的 @Component/@Service/@Repository 等 Bean;
- 解析 @EnableAutoConfiguration,读取 META-INF/spring/
org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,加载自动配置类; - 解析 @Bean 注解,注册手动声明的 Bean;
- 将所有 Bean 定义注册到 IoC 容器 finishBeanFactoryInitialization(beanFactory)
实例化所有非懒加载 Bean,完成依赖注入、初始化方法(@PostConstruct)执行
关键补充说明
- 自动配置核心:
@EnableAutoConfiguration是自动配置的入口,Spring Boot 通过spring-boot-autoconfigure包中的自动配置类,实现 "按需加载"(如引入 redis 依赖则自动配置 RedisTemplate); - 扫描范围:默认扫描启动类所在包及其子包,可通过
@ComponentScan指定自定义扫描范围; - 核心目的:构建完整的 IoC 容器,管理所有 Bean 的生命周期,为应用提供依赖注入、AOP 等核心能力。
2.4 启动嵌入式 Tomcat:初始化 Web 服务器,对外提供服务
对于 Web 应用(引入 spring-boot-starter-web),Spring Boot 会自动启动嵌入式 Tomcat(默认),核心逻辑在 ServletWebServerApplicationContext 的 onRefresh 方法中,完成服务器创建、Servlet/Filter 绑定、端口监听等操作。
调用流程
创建 SpringApplication 实例 执行启动逻辑 创建应用上下文 初始化 Web 应用上下文 刷新上下文 容器刷新核心方法 Web 服务器初始化 创建 Tomcat 实例 绑定 Servlet/Filter 等组件 启动 Tomcat 服务器 SpringApplication.run() 入口方法 new SpringApplication(primarySources) application.run(args) createApplicationContext() context = new AnnotationConfigServletWebServerApplicationContext() refreshContext(context) context.refresh() onRefresh()
ServletWebServerApplicationContext 重写的刷新方法,专用于 Web 服务器启动 createWebServer()
- 根据 server.port 等配置创建 Tomcat 实例;
- 配置 Tomcat 基础路径、连接器(Connector)、引擎(Engine)等核心组件;
- 绑定上下文路径(server.servlet.context-path) getSelfInitializer()
- 从 IoC 容器中获取所有 ServletContextInitializer 实现类(如 DispatcherServletRegistrationBean);
- 扫描容器中的 @Servlet/@Filter 注解组件,封装为 ServletContextInitializer 实现类;
- Tomcat 创建 ServletContext 时,执行这些 Initializer,完成 DispatcherServlet、Filter 等组件的注册 finishRefresh()
- 调用 Tomcat.start() 启动服务器;
- 绑定端口监听,等待客户端请求;
- 发布 ApplicationStartedEvent 事件,标识应用启动完成
关键补充说明
- 服务器切换:若需将 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 应用上下文完成嵌入式服务器启动",其核心优势在于:
- 自动化:通过
spring.factories/ 自动配置类,实现 "按需加载",无需手动配置核心组件; - 标准化:固定的启动流程确保应用开发的一致性,降低配置成本;
- 可扩展:通过自定义
ApplicationListener/EnvironmentPostProcessor/BeanFactoryPostProcessor,可灵活扩展启动逻辑。
理解上述流程,不仅能帮助开发者定位启动过程中的异常(如配置加载失败、Bean 冲突、端口占用),也能为自定义 Spring Boot Starter、扩展框架能力提供底层支撑。