Spring Boot 源码解读方法论
约 1605 字大约 5 分钟
布欧-Lewyon
2026-05-15
首页 › Spring Boot › 导读与版本对齐 › Spring Boot 源码解读方法论
阅读 Spring Boot 源码不是"通读所有代码",而是按图索骥、从入口类切入、聚焦关键扩展点。本节给出实用方法论,帮助你在需要时快速定位和理解 Boot 的内部实现。
阅读策略
原则一:不从头读到尾
Spring Boot 源码量约 20 万行 + Spring Framework 约 80 万行。从第一行开始读是不现实的。正确做法:
- 带着问题读——"
@SpringBootApplication是怎么展开的"、"自动配置怎么加载的" - 从入口类向下钻取——找到关键方法,用 IDE 的"Call Hierarchy"溯源
- 聚焦接口与抽象类——理解设计意图比读实现细节更快
原则二:善用调试断点
在关键入口打上断点,运行时单步跟进:
// 推荐断点位置(启动调试模式运行应用即可触发)
SpringApplication.run() // 启动入口
AutoConfigurationImportSelector.selectImports() // 自动配置加载
DispatcherServlet.doDispatch() // 请求分发
TransactionInterceptor.invokeWithinTransaction() // 事务处理原则三:理解关键抽象角色
Boot 的核心架构围绕以下接口展开,掌握了它们就掌握了脉络:
| 接口/抽象类 | 作用 | 常见实现 |
|---|---|---|
ApplicationContextInitializer | 在 refresh 前回调,修改上下文 | ServletWebServerApplicationContext |
BeanFactoryPostProcessor | 修改 BeanDefinition 元数据 | ConfigurationClassPostProcessor |
BeanPostProcessor | 在 Bean 初始化前后处理 | AutowiredAnnotationBeanPostProcessor |
ImportSelector / DeferredImportSelector | 按条件导入配置类 | AutoConfigurationImportSelector |
ImportBeanDefinitionRegistrar | 手动注册 BeanDefinition | AopConfigUtils |
EnvironmentPostProcessor | 在 refresh 前修改 Environment | ConfigDataEnvironmentPostProcessor |
Condition | 条件注解的核心评估接口 | OnClassCondition / OnBeanCondition |
FactoryBean | 复杂 Bean 的工厂创建 | MapperFactoryBean |
Boot 启动流程源码导读
以 SpringApplication.run() 为入口,逐步向下追踪:
// 入口:你写的这一行
SpringApplication.run(DemoApplication.class, args);
// → SpringApplication 构造
// 关键读取:从 spring.factories 读取 ApplicationContextInitializer 和 ApplicationListener
// IDE 操作:在 SpringApplication 构造方法打断点,看 initializers 和 listeners 列表
// → run() 方法
// 第①步:StopWatch.start() ——启动计时
// 第②步:getRunListeners() ——加载 SpringApplicationRunListener
// 第③步:prepareEnvironment() ——创建 Environment
// 第④步:printBanner() ——打印 Banner
// 第⑤步:createApplicationContext() ——创建 ApplicationContext
// 第⑥步:prepareContext() ——准备上下文(回调初始化器、注册启动参数)
// 第⑦步:refreshContext() ——核心!AbstractApplicationContext.refresh()
// 第⑧步:afterRefresh() ——执行 CommandLineRunner / ApplicationRunner第⑦步 refresh() 是 Spring IoC 容器的核心,它在 AbstractApplicationContext 中定义了 12 个子步骤:
AbstractApplicationContext.refresh()
├── prepareRefresh() // 准备工作
├── obtainFreshBeanFactory() // 获取 BeanFactory
├── prepareBeanFactory() // 配置 BeanFactory 的标准特性
├── postProcessBeanFactory() // 子类扩展(占位符)
│
├── invokeBeanFactoryPostProcessors(beanFactory) // ★★★★★ 关键:执行所有 BeanFactoryPostProcessor
│ ├── BeanDefinitionRegistryPostProcessor // 可注册 BeanDefinition
│ │ └── ConfigurationClassPostProcessor // 处理 @Configuration、@ComponentScan、@Import
│ │ └── processConfigBeanDefinitions() → 解析所有 @Configuration 类
│ │ └── AutoConfigurationImportSelector.selectImports() → 加载自动配置
│ └── BeanFactoryPostProcessor // 修改 BeanDefinition
│
├── registerBeanPostProcessors(beanFactory) // 注册 BeanPostProcessor(按优先级排序)
├── initMessageSource() // 初始化消息源
├── initApplicationEventMulticaster() // 初始化事件广播器
├── onRefresh() // ★★★★ 创建内嵌 Web 容器(Tomcat / Jetty / Undertow)
│ └── ServletWebServerApplicationContext.createWebServer()
│ └── TomcatServletWebServerFactory.getWebServer() → new Tomcat()
├── registerListeners() // 注册监听器
├── finishBeanFactoryInitialization(beanFactory) // ★★★★★ 实例化所有单例 Bean
│ └── beanFactory.preInstantiateSingletons()
│ └── AbstractBeanFactory.getBean() → doGetBean() → 创建 Bean 实例
│ ├── createBeanInstance() // 反射创建对象(构造器)
│ ├── populateBean() // 属性填充(自动注入)
│ └── initializeBean() // 初始化(BeanPostProcessor)
│ ├── applyBeanPostProcessorsBeforeInitialization
│ ├── invokeInitMethods() // @PostConstruct + InitializingBean
│ └── applyBeanPostProcessorsAfterInitialization // AOP 代理创建在此
│ └── AbstractAutoProxyCreator.postProcessAfterInitialization()
│
└── finishRefresh() // 启动完成、发布 ContextRefreshedEvent
└── ServletWebServerApplicationContext → 启动 Web 服务器条件注解体系深度
Spring Boot 的自动配置通过条件注解实现精细控制,所有 @ConditionalOn* 注解最终都基于 Spring 的 @Conditional 机制:
@Conditional(OnClassCondition.class) ← @ConditionalOnClass
@Conditional(OnMissingClassCondition.class) ← @ConditionalOnMissingClass
@Conditional(OnBeanCondition.class) ← @ConditionalOnBean / @ConditionalOnMissingBean
@Conditional(OnPropertyCondition.class) ← @ConditionalOnProperty
@Conditional(OnResourceCondition.class) ← @ConditionalOnResource
@Conditional(OnWebApplicationCondition.class) ← @ConditionalOnWebApplication
@Conditional(OnExpressionCondition.class) ← @ConditionalOnExpressionConditionEvaluator 求值过程
ConfigurationClassParser.processImports()
│
└── ConditionEvaluator.shouldSkip(metadata, phase)
├── 获取类上所有 @Conditional 注解
├── 遍历每个 @Conditional 的 Condition 实现类
│ ├── 创建 Condition 实例
│ └── condition.matches(context, metadata)
│ ├── OnClassCondition → 读取 @ConditionalOnClass(name = ...)
│ │ └── ClassUtils.isPresent(className, classLoader) → 尝试加载
│ ├── OnBeanCondition → 检查 BeanDefinition 注册表中是否存在
│ │ └── beanFactory.getBeanNamesForType(type) → 检查
│ └── OnPropertyCondition → 从 Environment 读取属性
│ └── environment.getProperty(prefix + "." + name)
│
└── 任一 Condition 返回 false → shouldSkip = true(跳过该配置类)自定义 Condition
public class OnLinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String os = context.getEnvironment().getProperty("os.name");
return os != null && os.toLowerCase().contains("linux");
}
}
@Configuration
@Conditional(OnLinuxCondition.class) // 仅在 Linux 环境下生效
public class LinuxSpecificConfig {
@Bean
public SomeBean someBean() { ... }
}条件注解的执行阶段
Spring 在解析配置类时会执行两轮条件评估:
第一阶段:ConfigurationClassParser.processImports() 中立即求值
→ 判断是否需要跳过整个配置类
→ 跳过则整个配置类的所有 @Bean 都不注册
第二阶段:ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass() 中
→ 检查 @Conditional 中的 phase = PARSE_CONFIGURATION
→ 与第一阶段逻辑相同,用于某些需要延迟评估的场景扩展点全景图
Spring Boot 在整个启动流程中提供了丰富的扩展点,按执行顺序排列:
应用启动前
├── spring.factories / AutoConfiguration.imports ← 添加自动配置类
├── spring-autoconfigure-metadata.properties ← 配置类条件缓存加速
Environment 准备阶段
├── EnvironmentPostProcessor ← 修改 Environment 属性
├── ApplicationContextInitializer ← refresh 前回调
BeanFactoryPostProcessor 阶段
├── BeanDefinitionRegistryPostProcessor ← 注册 BeanDefinition
├── BeanFactoryPostProcessor ← 修改 BeanDefinition
├── ImportSelector / DeferredImportSelector ← 条件导入
├── ImportBeanDefinitionRegistrar ← 手动注册
Bean 实例化阶段
├── BeanPostProcessor.postProcessBeforeInitialization ← 初始化前
├── @PostConstruct / InitializingBean.afterPropertiesSet ← 初始化
├── BeanPostProcessor.postProcessAfterInitialization ← 初始化后(AOP 代理)
容器启动完成
├── ApplicationRunner ← 应用启动后回调
├── CommandLineRunner ← 应用启动后回调
├── ApplicationListener<ApplicationReadyEvent> ← 就绪事件监听生产意识:理解扩展点的执行顺序对排查 Bean 加载问题至关重要。例如:
BeanFactoryPostProcessor阶段创建的 Bean 不会被BeanPostProcessor处理(因为后者还没注册)。自定义ApplicationListener<ApplicationReadyEvent>在就绪事件发布后执行——此时所有 Bean 已初始化完毕,可以安全依赖任何 Bean。
常用源码定位技巧
| 需求 | 搜索/断点方法 |
|---|---|
| 找某个 Starter 的自动配置类 | IDEA Ctrl+N → *AutoConfiguration(如 DataSourceAutoConfiguration) |
| 找 @Conditional 的匹配条件 | 追踪 Condition.matches() 实现(如 OnClassCondition) |
| 找何时创建了某个 Bean | 在 AbstractBeanFactory.doGetBean() 打条件断点 |
| 找某个注解的处理器 | 搜索 *PostProcessor 或 *Registrar(如 AsyncAnnotationBeanPostProcessor) |
| 找配置文件加载路径 | ConfigDataEnvironmentPostProcessor |
| 找 MVC 处理链 | DispatcherServlet.doDispatch() |
小结
- Spring Boot 源码阅读策略:带着问题读、IDE 断点追踪、聚焦关键抽象接口。
- IoC 容器核心在
AbstractApplicationContext.refresh()的 12 个步骤,特别是invokeBeanFactoryPostProcessors和finishBeanFactoryInitialization。 - 条件注解体系:
@ConditionalOnClass/@OnBean/@OnProperty等统一基于Condition接口,分两阶段求值。 - 扩展点全景:从
EnvironmentPostProcessor到ApplicationRunner覆盖了整个启动流程。 - 思考任务:在本地 IDE 中打开 Spring Boot 源码,从
SpringApplication.run()入口单步调试到refreshContext(),在onRefresh()处确认内嵌 Tomcat 的创建;自定义一个ApplicationContextInitializer在启动时打印环境变量 "custom.key" 的值,验证扩展点生效。
上一节:Spring Boot 概述
下一节:快速入门
