SpringNotes

第 31 章:源码阅读路线

zjc 于 2026-01-31 发布

这是《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

重点问题:

  1. BeanDefinition 从哪里来;
  2. BeanPostProcessor 何时注册;
  3. 单例缓存如何工作;
  4. 依赖注入如何解析候选者;
  5. Bean 生命周期回调顺序。

31.4 Bean 生命周期阅读

核心方法:

AbstractAutowireCapableBeanFactory.createBean
  -> createBeanInstance
  -> populateBean
  -> initializeBean
     -> invokeAwareMethods
     -> applyBeanPostProcessorsBeforeInitialization
     -> invokeInitMethods
     -> applyBeanPostProcessorsAfterInitialization

断点建议:

  1. createBeanInstance:观察构造器选择;
  2. populateBean:观察依赖注入;
  3. initializeBean:观察初始化回调;
  4. postProcessAfterInitialization:观察 AOP 代理;
  5. destroySingleton:观察销毁流程。

调试时可以在自定义 Bean 的构造器、@PostConstruct@PreDestroy 打日志,把源码顺序和业务观察对应起来。

31.5 AOP 阅读路线

入口:

@EnableAspectJAutoProxy

路线:

AnnotationAwareAspectJAutoProxyCreator
  -> findCandidateAdvisors
  -> buildAspectJAdvisors
  -> shouldSkip / findEligibleAdvisors
  -> createProxy
     -> JdkDynamicAopProxy
     -> ObjenesissCglibAopProxy
  -> DynamicAdvisedInterceptor.intercept
  -> ReflectiveMethodInvocation.proceed

重点问题:

  1. Aspect 注解如何解析成 Advisor;
  2. 代理何时生成;
  3. Advice 执行链如何组织;
  4. 为什么自调用失效;
  5. @Transactional 如何复用 AOP。

31.6 事务源码

入口:

@EnableTransactionManagement

路线:

TransactionAutoConfiguration
  -> ProxyTransactionManagementConfiguration
  -> TransactionInterceptor
  -> TransactionAspectSupport.invokeWithinTransaction
  -> PlatformTransactionManager.getTransaction
  -> DataSourceTransactionManager.doBegin
  -> commit / rollback

重点看:

  1. 事务属性解析;
  2. 传播行为处理;
  3. rollbackFor 匹配;
  4. 连接绑定 ThreadLocal;
  5. savepoint 创建;
  6. 挂起和恢复事务。

31.7 Spring MVC 源码

一次请求:

DispatcherServlet.doService
  -> doDispatch
  -> HandlerMapping.getHandler
  -> HandlerAdapter.handle
  -> RequestMappingHandlerAdapter.invokeHandlerMethod
  -> InvocableHandlerMethod.invokeForRequest
  -> HandlerMethodReturnValueHandler
  -> HttpMessageConverter

重点问题:

  1. URL 如何映射到 HandlerMethod;
  2. 参数如何解析;
  3. 校验何时触发;
  4. 异常如何进入 HandlerExceptionResolver;
  5. 返回值如何序列化;
  6. Filter、Interceptor、ControllerAdvice 的顺序。

31.8 Spring Boot 自动装配源码

入口:

@EnableAutoConfiguration

路线:

AutoConfigurationImportSelector
  -> getAutoConfigurationEntry
  -> ImportAutoConfigurationImportSelector
  -> AutoConfigurationSorter
  -> ConditionEvaluator
  -> OnClassCondition / OnBeanCondition / OnPropertyCondition

Spring Boot 3 中自动配置类从 AutoConfiguration.imports 读取;旧版本从 spring.factories 读取。

重点问题:

  1. 候选配置如何过滤;
  2. 条件报告如何生成;
  3. 配置顺序如何排序;
  4. 用户 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 和自动装配六条主线进入。先通过断点和日志观察行为,再阅读实现,把调用链画成图,并用最小实验验证理解。版本差异是源码学习中必须持续关注的边界。

思考题

  1. refresh() 中哪些阶段最重要?
  2. AOP 代理是在哪个生命周期阶段生成的?
  3. @Transactional 的核心入口是哪个类?
  4. 一次 REST 请求经过哪些核心组件?
  5. 如何验证自动配置条件为什么不匹配?