Java Web 学习笔记 —— 后端进阶(二):Spring Boot 原理深度解析(2026 年视角)
Spring Boot 的“魔法”其实就是一套精心设计的约定 > 配置 + 自动装配 + 事件驱动 + 生命周期管理机制。
到 2026 年,Spring Boot 3.2.x / 3.3.x 已经非常成熟,启动性能优化(AOT、GraalVM Native 支持)、虚拟线程集成、结构化日志等新特性已经融入核心,但最核心的启动流程与自动配置原理变化不大。
下面从“为什么这么简单就能跑起来”的角度,拆解最核心的几条主线(带源码关键路径)。
一、@SpringBootApplication 到底包含了什么?(三剑客)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
点开 @SpringBootApplication:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 1. 标记这是一个配置类(等价 @Configuration)
@EnableAutoConfiguration // 2. 开启自动配置(最核心!)
@ComponentScan( // 3. 组件扫描(默认当前包及其子包)
excludeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
includeFilters = @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
)
public @interface SpringBootApplication { ... }
三剑客各自职责:
| 注解 | 核心作用 | 底层实现关键类 |
|---|---|---|
| @SpringBootConfiguration | 声明这是一个 Spring 配置类 | — |
| @EnableAutoConfiguration | 开启自动配置(最重要的魔法) | AutoConfigurationImportSelector |
| @ComponentScan | 扫描当前包及其子包下的 @Component 等 | ClassPathBeanDefinitionScanner |
二、Spring Boot 启动流程全景(SpringApplication.run() 核心步骤)
public static ConfigurableApplicationContext run(Class<?>... primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
run() 方法核心流程(简化版,2026 年视角):
- 创建 SpringApplication 实例(构造函数)
- 推断应用类型(Servlet / Reactive / None)
- 设置 Application Type(Servlet → AnnotationConfigServletWebServerApplicationContext)
- 加载所有 ApplicationContextInitializer(初始化器)
- 加载所有 ApplicationListener(监听器)
- 推断主类(main 方法所在类)
- run() 方法执行 12 大步骤(最核心部分)
run() 方法内部主要做了以下事(伪代码顺序):
1. StopWatch 计时开始
2. 创建并启动 SpringApplicationRunListeners(发布 ApplicationStartingEvent)
3. 准备环境(prepareEnvironment):加载 application.properties/yaml、命令行参数、Profile 等
4. 创建并准备 ApplicationContext(createApplicationContext + prepareContext)
5. 刷新上下文前准备(prepareContext):绑定环境、加载 banner、发布 ApplicationEnvironmentPreparedEvent
6. 刷新上下文(refreshContext):调用 Spring 经典的 refresh() 方法(BeanFactoryPostProcessor、BeanPostProcessor、实例化单例等)
7. 发布 ApplicationStartedEvent / ApplicationReadyEvent
8. 执行 Runners(ApplicationRunner / CommandLineRunner)
9. 异常处理 & 优雅关闭钩子
10. 计时结束 & 日志输出启动耗时
关键节点时间线(2026 年典型启动耗时占比参考):
- 环境准备:~10–15%
- 自动配置加载 & 条件评估:~25–35%(最耗时部分)
- Bean 定义加载 & 实例化:~30–40%
- 内嵌容器启动(Tomcat/Jetty/Undertow):~10–20%
- Runners 执行:~5%
三、自动配置(Auto-Configuration)的核心原理(最常考)
自动配置的本质一句话:“根据类路径中存在的 jar 包,按条件加载对应的 xxxAutoConfiguration 类”。
核心链路(@EnableAutoConfiguration → AutoConfigurationImportSelector):
@EnableAutoConfiguration→@Import(AutoConfigurationImportSelector.class)- AutoConfigurationImportSelector 实现 DeferredImportSelector + Group
- 在
processImports()阶段调用getAutoConfigurationEntry() - 从
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.0+ 新格式)或旧的spring.factories读取所有候选自动配置类 - 条件过滤(@Conditional 家族):
- @ConditionalOnClass
- @ConditionalOnMissingBean
- @ConditionalOnProperty
- @ConditionalOnWebApplication
- @ConditionalOnExpression
- @ConditionalOnResource
- …
2026 年变化点(面试常问):
- Spring Boot 3.0+ 优先使用
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(纯文本,加载更快) - AOT(Ahead-of-Time)编译时会提前评估所有 @Conditional,生成静态 Bean 定义(GraalVM Native 关键)
- 启动性能优化:延迟初始化(@Lazy)、Bean 预加载、Class 数据共享(CDS)
四、常见面试/源码追问链(2025–2026 高频)
- Spring Boot 启动类为什么可以不写 @Configuration?
→ 因为 @SpringBootApplication 包含了 @SpringBootConfiguration - 自动配置类是怎么被加载的?为什么加了 starter 就能自动生效?
→ spring.factories / .imports 文件 + SpringFactoriesLoader / ImportSelectors - @ConditionalOnMissingBean 是什么时候生效的?
→ 在 AutoConfiguration 导入阶段(ConfigurationClassPostProcessor) - 为什么自定义的 Bean 能覆盖自动配置的 Bean?
→ 因为用户定义的 Bean 先加载(@ComponentScan 先扫描),@ConditionalOnMissingBean 看到已存在就不加载自动的 - Spring Boot 如何实现“jar 包直接运行”?
→ spring-boot-maven-plugin 打包成可执行 jar(包含 org.springframework.boot.loader)+ 内嵌容器 - 如何自定义 Starter?(最常手写题)
- 写 xxxAutoConfiguration + META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 写 xxxProperties + @ConfigurationProperties
- 打包成 starter jar(不带 main 方法)
- Spring Boot 3+ 与 2.x 启动流程最大区别?
→ AOT 支持、GraalVM Native、虚拟线程默认支持、Jakarta EE 迁移、.imports 文件取代部分 factories
五、总结一句话口诀(背下来)
“Spring Boot = Spring + 约定优于配置 + 自动配置 + 内嵌容器 + 可执行 Jar + 事件驱动 + 条件装配”
核心魔法链:
@SpringBootApplication → @EnableAutoConfiguration → AutoConfigurationImportSelector → spring.factories / .imports → @Conditional 条件过滤 → Bean 定义 → refresh() 刷新容器
你现在对 Spring Boot 原理最想搞清楚的是哪一块?
是启动流程详细源码、自动配置条件评估细节、自定义 Starter 实战、AOT/GraalVM Native 变化,还是 Spring Boot 3+ 与 2.x 的差异对比?
可以继续针对性深挖~