# spring-framework-4.3-study **Repository Path**: zhxgxn/spring-framework-4.3-study ## Basic Information - **Project Name**: spring-framework-4.3-study - **Description**: spring源码学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: spring-4.3-annotated - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-11 - **Last Updated**: 2026-03-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring 4.3.x 源码阅读手册 > **架构师寄语**:源码不是用来读的,是用来“跑”的。带着问题去 Debug,比死记硬背类名更重要。 > 学习是为了找到通往答案的路径和方法,是为了拥有无师自通的能力 ## 如何阅读源码 1. **接口抽象定义**。任何代码都会有很多接口或抽象定义,其描述了代码需要处理的数据结构或者业务实体,以及它们之间的关系,理清楚这些关系是非常重要的。 2. **模块粘合层**。我们的代码有很多都是用来粘合代码的,比如中间件(middleware)、Promises 模式、回调(Callback)、代理委托、依赖注入等。这些代码模块间的粘合技术是非常重要的,因为它们会把本来平铺直述的代码给分裂开来,让你不容易看明白它们的关系。 3. **业务流程**。这是代码运行的过程。一开始,我们不要进入细节,但需要在高层搞清楚整个业务的流程是什么样的,在这个流程中,数据是怎么被传递和处理的。一般来说,我们需要画程序流程图或者时序处理图。 4. **具体实现** 。了解上述的三个方面的内容,相信你对整个代码的框架和逻辑已经有了总体认识。这个时候,你就可以深入细节,开始阅读具体实现的代码了。对于代码的具体实现,一般来说,你需要知道下面一些事实,这样有助于你在阅读代码时找到重点。 - 代码逻辑。代码有两种逻辑,一种是业务逻辑,这种逻辑是真正的业务处理逻辑;另一种是控制逻辑,这种逻辑只是用控制程序流转的,不是业务逻辑。比如:flag 之类的控制变量,多线程处理的代码,异步控制的代码,远程通讯的代码,对象序列化反序列化的代码等。这两种逻辑你要分开,很多代码之所以混乱就是把这两种逻辑混在一起了(详情参看《编程范式游记》)。 - 出错处理。根据二八原则,20% 的代码是正常的逻辑,80% 的代码是在处理各种错误,所以,你在读代码的时候,完全可以把处理错误的代码全部删除掉,这样就会留下比较干净和简单的正常逻辑的代码。排除干扰因素,可以更高效地读代码。 - 数据处理。只要你认真观察,就会发现,我们好多代码就是在那里倒腾数据。比如 DAO、DTO,比如 JSON、XML,这些代码冗长无聊,不是主要逻辑,可以不理。 - 重要的算法。一般来说,我们的代码里会有很多重要的算法,我说的并不一定是什么排序或是搜索算法,可能会是一些其它的核心算法,比如一些索引表的算法,全局唯一 ID 的算法、信息推荐的算法、统计算法、通读算法(如 Gossip)等。这些比较核心的算法可能会非常难读,但它们往往是最有技术含量的部分。 - 底层交互。有一些代码是和底层系统的交互,一般来说是和操作系统或是 JVM 的交互。因此,读这些代码通常需要一定的底层技术知识,不然,很难读懂。 5. **运行时调试**。很多时候,代码只有运行起来了,才能知道具体发生了什么事,所以,我们让代码运行进来,然后用日志也好,debug 设置断点跟踪也好。实际看一下代码的运行过程,是了解代码的一种很好的方式。 6. **阅读代码方式如下**: - 一般采用自顶向下,从总体到细节的“剥洋葱皮”的读法。 - 画图是必要的,程序流程图,调用时序图,模块组织图…… - 代码逻辑归一下类,排除杂音,主要逻辑才会更清楚。 - debug 跟踪一下代码是了解代码在执行中发生了什么的最好方式。 --- ## 核心主线:Spring 容器启动全流程 (`refresh`) 关键类: `BeanDefinitionReader -> BeanFactory -> BeanDefinition。` 定位类:`org.springframework.context.support.AbstractApplicationContext` 方法:`public void refresh() throws BeansException, IllegalStateException` ### 1. 扫描与解析(元数据准备) 重点关注如何将你的 Java 类变成 `BeanDefinition`。 理解: Spring 并不是直接反射创建对象,而是先将配置解析为 BeanDefinition(元数据),这体现了解耦的思想。 - [ ] **关键断点**:`invokeBeanFactoryPostProcessors(beanFactory)` - [ ] **核心类**:`ConfigurationClassPostProcessor` - [ ] **思考**:Spring 是如何处理 `@Import`、`@ComponentScan` 和 `@Bean` 的优先级顺序的? ### 2. Bean 的生命周期(生产流水线)refresh() 十二个步骤 重点关注 `finishBeanFactoryInitialization(beanFactory)`,这是核心中的核心。 - [ ] **链路追踪**:`getBean()` -> `doGetBean()` -> `createBean()` -> `doCreateBean()` - [ ] **三大阶段断点**: 1. **实例化**:`createBeanInstance` (反射/工厂方法) 2. **属性填充**:`populateBean` (处理 `@Autowired`, `@Value`) 3. **初始化**:`initializeBean` (执行 `Aware` 接口、`BeanPostProcessor`、`init-method`) - [ ] 理解: Spring 并不是直接反射创建对象,而是先将配置解析为 BeanDefinition(元数据),这体现了解耦的思想。 ### PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 流程图 ![](./images/30824817991700.png) # Spring AOP源码调试与阅读指南 本文档详细介绍 Spring AOP源码的阅读路径和核心概念,帮助深入理解 Spring AOP 的实现原理。 ## 目录 1. [AOP 基本概念](#一-aop-基本概念) 2. [AOP代理生成流程](#二-aop-代理生成流程) 3. [CGLIB代理生成](#三-cglib-代理的流程) 4. [Advisor解析流程](#四-advisor-解析流程) 5. [拦截器链构建流程](#五-spring-aop-拦截器链构建流程) 6. [拦截器执行流程](#六-spring-aop-拦截器链递归执行流程) --- ## 一、AOP 基本概念 ### 1. 核心架构 **Spring AOP 整体架构图** ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Spring AOP 整体架构 │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ @Enable │ │ @Aspect │ │ XML 配置 │ │ │ │ AspectJAutoProxy│ │ 切面类 │ │ aop:aspect │ │ │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ │ │ │ └──────────────────────┼──────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────┐ │ │ │ AnnotationAwareAspectJAutoProxyCreator │ │ │ │ (BeanPostProcessor 实现) │ │ │ └─────────────────────┬───────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────┐ │ │ │ postProcessAfterInitialization() │ │ │ │ 判断是否需要创建代理 │ │ │ └─────────────────────┬───────────────────────┘ │ │ ↓ │ │ ┌────────────────────────┐ │ │ │ 创建代理对象 │ │ │ │ JdkDynamicAopProxy │ │ │ │ CglibAopProxy │ │ │ └────────────┬───────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ 代理对象 │ │ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ │ │ 方法调用 → 拦截器链 → 目标方法执行 → 返回结果 │ │ │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ![](./images/29017315635700.png) --- ### 2. 基本概念 - **Join point(连接点)**: 所谓的连接点是指那些被拦截到的点。在 Spring AOP 中,连接点特指方法执行(包括构造方法、普通方法),因为 Spring 仅支持方法级别的拦截。AspectJ 还支持字段访问、构造器调用等其他连接点类型 - **Pointcut(切入点)**: 所谓的切入点,是指要对哪些 Join point(连接点)进行拦截的定义。如果 Join point(连接点)是全集,那么 Pointcut(切入点)就是被选中的子集。写 AOP 代码的时候,一般是用 Pointcut(切入点)表达式进行对 Join point(连接点)进行选择。 - **Advice(通知/增强)**: 所谓的通知就是指拦截到 Join point(连接点)之后所要做的事情。通知根据作用位置不同,又细分为: - **Before advice(前置通知)**: 在 Join point(连接点)之前运行的通知。这种通知,不能阻止执行流程继续到 Join point(连接点)。 - **After returning advice(后置通知)**: 在 Join point(连接点)之后运行的通知。当然,如果在 Join point(连接点)执行过程中,抛出异常,则可能就不执行了。 - **After throwing advice(异常通知)**: 方法抛出异常后,将会执行的通知。 - **After (finally) advice(最终通知)**: 无论如何都会执行的通知,即使抛出异常。 - **Around advice(环绕通知)**: 围绕在 Join point(连接点)的通知,方法执行前和执行后,都可以执行自定义行为。同时,也可以决定是返回 Join point(连接点)的返回值,还是返回自定义的返回值。 - **执行顺序**: `@Around(前置部分)` → `@Before` → `目标方法` → `@AfterReturning(正常)`/`@AfterThrowing(异常)` → `@After` → `@Around(后置部分)` - **Aspect(切面)**: 是切入点和通知的结合。 - **Advisor(通知器/顾问)**: 和 Aspect(切面)很相似,一个切入点 + 一个通知,单一职责 - **Introduction(引介)**: 引介是一种特殊的通知在不修改类代码的前提下,Introduction 可以在运行期为类动态地添加一些方法或属性。 - **Target object(目标对象)**: 代理的目标对象。 - **AOP proxy(代理)**: 一个类被 AOP 织入增强后,就产生一个结果代理类。 - **Weaving(织入)**: 是指把增强应用到目标对象来创建新的代理对象的过程。Spring 是通过实现后置处理器 BeanPostProcessor 接口来实现织入的。也就是在 Bean 完成初始化之后,通过给目标对象生成代理对象,并交由 Spring IoC 容器来接管,这样再去容器中获取到的目标对象就是已经增强过的代理对象。 | 层级 | 概念 | 职责 | 是否核心 | |------|------|------|----------| | **基础概念** | Joinpoint | 连接点,程序执行过程中的特定点(方法调用、构造器调用等) | ✅ 核心 | | | Pointcut | 切点,定义一组 Joinpoint 的匹配规则 | ✅ 核心 | | | Advice | 增强,在 Joinpoint 处执行的逻辑 | ✅ 核心 | | | Aspect | 切面,Pointcut + Advice 的模块化封装 | ✅ 核心 | | | Advisor | 通知者,Spring 内部将 Aspect 拆解为 Advisor(Pointcut + Advice) | ✅ 核心 | | **代理层** | AopProxy | 代理抽象,根据目标生成代理对象 | ✅ 核心 | | | TargetSource | 目标源,封装目标对象,支持连接池、热交换等 | 重要 | | | Advised | 被增强的接口,代理对象持有的元数据 | 重要 | | **执行层** | MethodInvocation | 方法调用上下文,封装调用链 | 重要 | | | MethodInterceptor | 方法拦截器,AOP Alliance 标准接口 | 重要 | | **工厂层** | ProxyFactory | 代理工厂,创建 AopProxy | 重要 | | | AopProxyFactory | 代理工厂的工厂,策略模式选择代理类型 | 重要 | | **自动代理层** | BeanPostProcessor | 后置处理器,触发代理创建 | 重要 | | | AdvisorAutoProxyCreator | 自动代理创建器 | 重要 | ![](./images/4623089788100.png) ![](./images/5024450312300.png) --- ### 3. 核心接口继承体系 #### Advice 继承体系 > 最顶层的标记接口,表示在连接点执行的动作。Spring 在此基础上扩展了多种通知类型 Advice = 做什么(逻辑) Advisor = 在哪儿做(Pointcut)+ 做什么(Advice) Advised = 有哪些要做(Advisor 列表)+ 目标是谁(TargetSource) ``` Advice (org.aopalliance.aop.Advice) │ ├── MethodInterceptor (org.aopalliance.intercept.MethodInterceptor) │ │ │ ├── AspectJAfterAdvice (After) │ ├── AspectJAfterReturningAdvice │ ├── AspectJAfterThrowingAdvice │ ├── AspectJAroundAdvice (Around) │ └── MethodBeforeAdviceInterceptor │ ├── MethodBeforeAdvice ├── AfterReturningAdvice ├── ThrowsAdvice └── IntroductionInterceptor ``` - Advisor 继承体系 > 切面控制器,将Advice和Pointcut组合在一起的容器 ``` Advisor (org.aopalliance.aop.Advice) │ ├── PointcutAdvisor (org.springframework.aop.PointcutAdvisor) │ │ │ ├── DefaultPointcutAdvisor │ ├── NameMatchMethodPointcutAdvisor │ ├── AspectJPointcutAdvisor │ └── AbstractPointcutAdvisor │ └── IntroductionAdvisor (org.springframework.aop.IntroductionAdvisor) │ └── DefaultIntroductionAdvisor ``` - Pointcut 继承体系 > 切入点 ``` Pointcut (org.springframework.aop.Pointcut) │ ├── AspectJExpressionPointcut ├── ComposablePointcut ├── ControlFlowPointcut ├── JdkRegexpMethodPointcut └── NameMatchMethodPointcut ClassFilter (org.springframework.aop.ClassFilter) │ └── RootClassFilter / TrueClassFilter / TypePatternClassFilter MethodMatcher (org.springframework.aop.MethodMatcher) │ ├── StaticMethodMatcher └── DynamicMethodMatcher ``` - AopProxy 继承体系 ``` AopProxy (org.springframework.aop.framework.AopProxy) │ ├── JdkDynamicAopProxy └── CglibAopProxy AopProxyFactory (org.springframework.aop.framework.AopProxyFactory) │ └── DefaultAopProxyFactory ProxyConfig (org.springframework.aop.framework.ProxyConfig) │ └── AdvisedSupport │ ├── ProxyFactory └── ProxyFactoryBean ``` - AutoProxyCreator 继承体系 ``` BeanPostProcessor │ └── AbstractAutoProxyCreator │ ├── AbstractAdvisorAutoProxyCreator │ │ │ └── AspectJAwareAdvisorAutoProxyCreator │ │ │ └── AnnotationAwareAspectJAutoProxyCreator │ └── InfrastructureAdvisorAutoProxyCreator ``` - MethodInvocation 继承体系 ``` JoinPoint (org.aspectj.lang.JoinPoint) │ └── ProceedingJoinPoint (org.aspectj.lang.ProceedingJoinPoint) │ └── MethodInvocation (org.aopalliance.intercept.MethodInvocation) │ └── ReflectiveMethodInvocation │ └── CglibMethodInvocation ``` --- ### 4. AOP 实现原理 **核心原则**:**如果使用接口,则用 JDK 的动态代理实现;如果没有实现接口,则使用 CGLIB 通过字节码技术来实现** ![](./images/4632641300900.png) JDK 的动态代理和 CGLIB 字节码技术在实现上也略有不同: ![](./images/4653454123800.png) --- ## 二、AOP代理生成流程 **AnnotationAwareAspectJAutoProxyCreator 类关系图**:![](images/ba772ef1.png) ### 核心流程 1. `AbstractAutoProxyCreator` 实现了核心代理创建,`postProcessAfterInitialization` 调用 `wrapIfNecessary` 方法来判断是否需要创建代理 ### 继承关系与配置传递 ``` AbstractAutoProxyCreator (配置源) │ ├── interceptors: String[] → 拦截器名称 ├── advisorAdapterRegistry → 适配器注册器 ├── freezeProxy: boolean → 是否冻结 ├── applyCommonInterceptorsFirst → 拦截器顺序 ├── proxyTargetClass: boolean → 代理策略 │ ↓ copyFrom() │ ProxyFactory (配置接收者) │ ├── advisors: List ← buildAdvisors() ├── targetSource: TargetSource ← setTargetSource() ├── proxyInterfaces: Class[] ← evaluateProxyInterfaces() ├── ... 其他配置 │ ↓ createAopProxy() │ AopProxy (执行者) │ ├── CglibAopProxy (类代理) └── JdkDynamicAopProxy (接口代理) ``` --- ### AOP代理的创建流程 ``` ┌─────────────────────────────────────────────────────────┐ │ createProxy(beanClass, beanName, │ │ specificInterceptors, targetSource) │ └─────────────────┬───────────────────────────────────────┘ │ ┌─────────────┼─────────────┐ │ │ │ ▼ ▼ ▼ ┌────────┐ ┌──────────┐ ┌──────────┐ │ 步骤 1 │ │ 步骤 2 │ │ 步骤 3 │ │ 暴露 │ │ 创建 │ │ 决定 │ │ 目标类 │ │ Factory │ │ 策略 │ └────────┘ └──────────┘ └──────────┘ │ │ │ └─────────────┼─────────────┘ │ ▼ ┌───────────────┐ │ 步骤 4-8 │ │ 构建 Advisor │ │ 设置配置 │ └───────┬───────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ 步骤 9: proxyFactory.getProxy() │ └─────────────────┬───────────────────────────────────────┘ │ ┌────────┴────────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ JdkDynamicAopProxy │ CglibAopProxy │ │ .getProxy() │ │ .getProxy() │ │ │ │ │ │ Proxy.new…() │ │ Enhancer.…() │ └─────────────────┘ └───────────────── ``` ![](./images/31528975737500.png) --- ## 三、CGLIB代理的流程 ![](./images/28215265251300.png) --- ## 四、Advisor解析流程 *(待补充)* --- ## 五、Spring AOP 拦截器链构建流程 ![](./images/26573098599900.png) --- ## 六、Spring AOP 拦截器链递归执行流程 学习了 `ReflectiveMethodInvocation` 中 `proceed()` 递归责任链调用的设计:**索引 + 递归的结合使用** ### 调用栈深度演示(假设 3 个拦截器) ``` Level 0: TransactionInterceptor.invoke(invocation) ├─ [前置] 开启事务 ├─→ invocation.proceed() ← 递归调用 │ │ Level 1: SecurityInterceptor.invoke(invocation) │ ├─ [前置] 权限校验 │ ├─→ invocation.proceed() ← 递归调用 │ │ │ │ Level 2: LogInterceptor.invoke(invocation) │ │ ├─ [前置] 记录开始时间 │ │ ├─→ invocation.proceed() ← 递归调用 │ │ │ │ │ │ Level 3: invokeJoinpoint() ← 到达链尾 │ │ │ └─→ method.invoke(target, args) │ │ │ └─【真正执行业务逻辑】 │ │ │ │ │ ├─ [后置] 记录耗时 │ │ └─← return result │ │ │ ├─ [后置] 释放权限上下文 │ └─← return result │ ├─ [后置] 提交事务 └─← return result(最终返回给客户端) ``` ![](./images/33352163921000.png) --- ## 七、时序图 *(待补充)* --- ## 参考资料 - https://www.processon.com/diagraming/5e9e54f61e085346f7104fe3 - https://www.diguage.com/post/to-learn/ - https://schunter.doocs.org/Spring --- **文档版本**: 1.0 **最后更新**: 2026-03-23 **基于 Spring Framework**: 4.3.x