这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 读 Spring 源码的目的不是背类名,而是理解框架如何管理 Bean、启动上下文、处理请求、实现事务代理和自动装配。源码浩大,必须从问题进入,沿着一次请求或一次启动流程走。
31.1 准备源码
获取源码:
git clone https://github.com/spring-projects/spring-framework.git
git clone https://github.com/spring-projects/spring-boot.git
建议选择与项目相同的 release 分支。日常开发不必自己编译整个 Spring,可直接下载 source jar 或在 IDE 中自动关联源码。
Maven 下载源码:
mvn dependency:sources
31.2 模块地图
spring-core
|-- core
|-- beans
|-- context
|-- aop
|-- tx
|-- web
+-- webmvc
spring-boot
|-- spring-boot
|-- spring-boot-autoconfigure
|-- spring-boot-actuator
+-- starters
| 模块 | 重点 |
|---|---|
| spring-beans | BeanDefinition、BeanFactory、生命周期 |
| spring-context | 事件、扩展点、refresh |
| spring-aop | 代理、切点、Advisor |
| spring-tx | 事务拦截器和传播行为 |
| spring-webmvc | DispatcherServlet 请求链 |
| spring-boot | SpringApplication 启动流程 |
| autoconfigure | 条件装配和 Starter |
31.3 IoC 阅读路线
入口:
SpringApplication.run(OrderApplication.class, args);
推荐路线:
SpringApplication.run
-> createApplicationContext
-> refreshContext
-> AbstractApplicationContext.refresh
-> invokeBeanFactoryPostProcessors
-> ConfigurationClassPostProcessor
-> finishBeanFactoryInitialization
-> DefaultListableBeanFactory.preInstantiateSingletons
-> AbstractBeanFactory.doGetBean
-> AbstractAutowireCapableBeanFactory.createBean
重点问题:
- BeanDefinition 从哪里来;
- BeanPostProcessor 何时注册;
- 单例缓存如何工作;
- 依赖注入如何解析候选者;
- Bean 生命周期回调顺序。
31.4 Bean 生命周期阅读
核心方法:
AbstractAutowireCapableBeanFactory.createBean
-> createBeanInstance
-> populateBean
-> initializeBean
-> invokeAwareMethods
-> applyBeanPostProcessorsBeforeInitialization
-> invokeInitMethods
-> applyBeanPostProcessorsAfterInitialization
断点建议:
createBeanInstance:观察构造器选择;populateBean:观察依赖注入;initializeBean:观察初始化回调;postProcessAfterInitialization:观察 AOP 代理;destroySingleton:观察销毁流程。
调试时可以在自定义 Bean 的构造器、@PostConstruct、@PreDestroy 打日志,把源码顺序和业务观察对应起来。
31.5 AOP 阅读路线
入口:
@EnableAspectJAutoProxy
路线:
AnnotationAwareAspectJAutoProxyCreator
-> findCandidateAdvisors
-> buildAspectJAdvisors
-> shouldSkip / findEligibleAdvisors
-> createProxy
-> JdkDynamicAopProxy
-> ObjenesissCglibAopProxy
-> DynamicAdvisedInterceptor.intercept
-> ReflectiveMethodInvocation.proceed
重点问题:
- Aspect 注解如何解析成 Advisor;
- 代理何时生成;
- Advice 执行链如何组织;
- 为什么自调用失效;
@Transactional如何复用 AOP。
31.6 事务源码
入口:
@EnableTransactionManagement
路线:
TransactionAutoConfiguration
-> ProxyTransactionManagementConfiguration
-> TransactionInterceptor
-> TransactionAspectSupport.invokeWithinTransaction
-> PlatformTransactionManager.getTransaction
-> DataSourceTransactionManager.doBegin
-> commit / rollback
重点看:
- 事务属性解析;
- 传播行为处理;
- rollbackFor 匹配;
- 连接绑定 ThreadLocal;
- savepoint 创建;
- 挂起和恢复事务。
31.7 Spring MVC 源码
一次请求:
DispatcherServlet.doService
-> doDispatch
-> HandlerMapping.getHandler
-> HandlerAdapter.handle
-> RequestMappingHandlerAdapter.invokeHandlerMethod
-> InvocableHandlerMethod.invokeForRequest
-> HandlerMethodReturnValueHandler
-> HttpMessageConverter
重点问题:
- URL 如何映射到 HandlerMethod;
- 参数如何解析;
- 校验何时触发;
- 异常如何进入 HandlerExceptionResolver;
- 返回值如何序列化;
- Filter、Interceptor、ControllerAdvice 的顺序。
31.8 Spring Boot 自动装配源码
入口:
@EnableAutoConfiguration
路线:
AutoConfigurationImportSelector
-> getAutoConfigurationEntry
-> ImportAutoConfigurationImportSelector
-> AutoConfigurationSorter
-> ConditionEvaluator
-> OnClassCondition / OnBeanCondition / OnPropertyCondition
Spring Boot 3 中自动配置类从 AutoConfiguration.imports 读取;旧版本从 spring.factories 读取。
重点问题:
- 候选配置如何过滤;
- 条件报告如何生成;
- 配置顺序如何排序;
- 用户 Bean 如何覆盖默认 Bean。
31.9 高效调试技巧
条件断点:
beanName.equals("orderService")
method.getName().equals("createOrder")
request.getRequestURI().equals("/api/orders")
辅助 Bean:
@Component
public class LifecycleDebugBean {
@PostConstruct
public void afterProperties() {
System.out.println("order service initialized");
}
@PreDestroy
public void beforeDestroy() {
System.out.println("order service destroyed");
}
}
观察 Bean:
applicationContext.getBeansOfType(Object.class).size();
applicationContext.getBeanDefinitionNames();
建议新建最小工程,只保留被研究的问题,避免业务代码干扰。
31.10 阅读方法
推荐流程:
1. 提出一个具体问题
2. 从入口断点确认调用链
3. 画出时序图
4. 标记关键扩展点
5. 写一个最小复现实验
6. 对比不同版本
7. 记录结论和边界
不要试图从第一个类线性读完所有源码。Spring 的价值在主流程和扩展模型,理解这两层后,其余代码会更容易定位。
本章小结
Spring 源码阅读应从启动、Bean 生命周期、AOP、事务、MVC 和自动装配六条主线进入。先通过断点和日志观察行为,再阅读实现,把调用链画成图,并用最小实验验证理解。版本差异是源码学习中必须持续关注的边界。
思考题
refresh()中哪些阶段最重要?- AOP 代理是在哪个生命周期阶段生成的?
@Transactional的核心入口是哪个类?- 一次 REST 请求经过哪些核心组件?
- 如何验证自动配置条件为什么不匹配?