aop
https://mp.weixin.qq.com/s/xvidIGCL4mIYfGni4pq9wQ
https://mp.weixin.qq.com/s/UBE9CqASb-i9sRt715ckGA
https://mp.weixin.qq.com/s/oFQfS_nOp_yMfDQ4yhSBNA
通过创建流程,执行流程,类体系三个角度理解aop
创建对象流程:(BeanPostProcessor后置处理,Advisor类匹配)
Spring AOP 创建代理对象的过程是一个非常经典且复杂的流程,主要发生在 Bean 的生命周期 中的 后置处理(Post Processing) 阶段。
核心组件是 AbstractAutoProxyCreator(这是一个 BeanPostProcessor)。
以下是精简后的核心流程步骤:
1. 寻找候选者(Find Candidates)
当 Spring 容器初始化一个 Bean(比如 UserService)并填充完属性后,AbstractAutoProxyCreator 会介入。
任务:它要去容器里找所有的 Advisor(切面通知器)。
Advisor 是什么?:一个 Advisor = 一个切点(Pointcut)+ 一个通知(Advice/Interceptor)。
动作:Spring 会遍历容器里所有的 Bean,找出所有实现了 Advisor 接口的 Bean(比如事务 Advisor、日志 Advisor)。
2. 筛选匹配(Filter & Match)
找到一堆 Advisor 后,Spring 需要判断:这些 Advisor 跟当前这个 UserService Bean 有关系吗?
动作:遍历每一个 Advisor。
判断:用 Advisor 里的 Pointcut(切点表达式)去匹配 UserService 类及其所有方法。
如果 Pointcut 说 execution(* com.service..(..)),而 UserService 刚好在 com.service 包下。
结果:匹配成功!这个 Advisor 属于这个 Bean。
3. 排序(Sort)
如果一个 Bean 匹配了多个 Advisor(比如既有事务,又有日志,又有安全),需要决定谁先谁后。
规则:根据 @Order 注解或 Ordered 接口进行排序。
结果:得到一个有序的 Advisor 列表,比如 [LogAdvisor, TxAdvisor]。
4. 创建代理(Create Proxy)
只要匹配到了至少一个 Advisor,Spring 就决定要为这个 Bean 创建代理。
决策:用 JDK 动态代理还是 CGLIB?
如果目标类实现了接口 -> 默认用 JDK 动态代理。
如果目标类没实现接口 -> 强制用 CGLIB。
如果配置了 proxyTargetClass=true -> 强制用 CGLIB。
执行:
调用 ProxyFactory。
把目标对象(Target)塞进去。
把刚才筛选出来的有序 Advisor 列表塞进去。
生成代理对象(Proxy Object)。
5. 替换(Replace)
最终结果:Spring 容器会用这个新生成的 代理对象 替换掉原本的 原生对象。
影响:以后任何地方 Use @Autowired UserService,注入进来的都是这个代理对象。
总结流程图
Bean初始化完成
|
v
[AbstractAutoProxyCreator.postProcessAfterInitialization]
|
+---> 1. 扫描所有的 Advisor (切面)
|
+---> 2. 筛选: 哪些 Advisor 的 Pointcut 能匹配当前 Bean?
| (如果没有匹配的 -> 直接返回原生对象)
|
+---> 3. 排序: 对匹配的 Advisor 排序
|
+---> 4. 创建代理:
| ProxyFactory.getProxy()
| (JDK 或 CGLIB)
|
v
返回代理对象 (放入 Spring 容器单例池)代理类被调用时的执行流程
当我们在 Spring 容器中拿到代理对象并调用其方法时(比如 userService.login()),代理对象内部会触发一个精密的拦截器链执行流程。
核心是 JDK 的 InvocationHandler 或 CGLIB 的 DynamicAdvisedInterceptor。尽管入口不同,但它们最终都会汇聚到同一个核心逻辑上:ReflectiveMethodInvocation.proceed()。
以下是详细的执行步骤:
1. 代理对象拦截 (Entry Point)
动作:调用 proxy.login()。
JDK 场景:进入 JdkDynamicAopProxy.invoke()。
CGLIB 场景:进入 DynamicAdvisedInterceptor.intercept()。
任务:它们首先会判断这个方法是否需要拦截(也就是是否匹配某个 Advisor)。如果不需要拦截(比如 toString() 或者未配置切点的方法),直接反射调用目标对象。
2. 获取拦截器链 (Get Interceptor Chain)
如果该方法需要被增强,代理对象会向配置中心(AdvisedSupport)索要该方法的拦截器链。
动作:List<Object> chain = advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
结果:拿到一个列表,比如 [ExposeInvocationInterceptor, TransactionInterceptor, LogInterceptor]。
注:Spring 会把 Advisor 转换成 MethodInterceptor 放在这个链里。
3. 启动调用链 (Start Invocation)
Spring 创建一个核心对象:ReflectiveMethodInvocation。
它封装了所有信息:代理对象、目标对象、目标方法、参数、拦截器链。
动作:调用 invocation.proceed()。
4. 递归/链式执行 (The Chain Proceeding)
这是最精彩的“递归”部分(实际上是用索引实现的伪递归)。ReflectiveMethodInvocation 内部维护了一个索引 currentInterceptorIndex(初始为 -1)。
第 1 次调用 proceed():
索引 +1 -> 拿到链中第 1 个拦截器(比如 ExposeInvocationInterceptor)。
执行该拦截器的 invoke(this) 方法。
拦截器做完前置工作后,必须显式调用 invocation.proceed()。
第 2 次调用 proceed():
索引 +1 -> 拿到链中第 2 个拦截器(比如 TransactionInterceptor)。
执行 invoke(this)。
它开启事务 -> 调用 invocation.proceed()。
第 3 次调用 proceed():
索引 +1 -> 拿到链中第 3 个拦截器(比如 LogInterceptor)。
执行 invoke(this)。
它打印日志 -> 调用 invocation.proceed()。
5. 执行目标方法 (Invoke Target)
第 4 次调用 proceed():
索引 +1 -> 发现超出了链的长度(拦截器用光了)。
终极动作:调用真实的目标方法 method.invoke(target, args)。
执行实际的 login() 业务逻辑。
拿到返回值 retVal。
6. 回溯 (Return / Unwind)
方法调用栈开始出栈(也就是代码里的 proceed() 方法返回了):
回到第 3 个(Log):proceed() 返回了。LogInterceptor 记录“方法结束时间”,然后返回 retVal。
回到第 2 个(Tx):proceed() 返回了。TransactionInterceptor 提交事务,然后返回 retVal。
回到第 1 个(Expose):清理 ThreadLocal,返回 retVal。
7. 返回最终结果
- 代理对象的 invoke 方法拿到最终的 retVal,返回给最外层的调用者。
图解递归流程
Caller
|
v
Proxy.login()
|
+-> ReflectiveMethodInvocation.proceed()
|
+-> [1] TransactionInterceptor.invoke()
| |--> 开启事务
| |--> invocation.proceed()
| |
| +-> [2] LogInterceptor.invoke()
| |--> 打印 Start
| |--> invocation.proceed()
| |
| +-> [3] 链跑完了 -> Target.login()
| |
| |<-- (return result)
| |--> 打印 End
| |<-- (return result)
| |<-- 提交事务
|<-- (return result)
|<-- (return result)Spring AOP 的类继承体系(切点,通知增强,代理)
虽然庞大,但核心骨架非常清晰。可以将其分为三大阵营:核心 API(AOP 联盟标准)、Spring 的基础封装(Support)、创建与代理(Creator & Proxy)。
1. 核心接口(基于 AOP Alliance 标准)
这部分是所有 AOP 框架通用的标准,定义了最基本的概念。
Advice (标记接口)
^
|-- Interceptor (拦截器)
| ^
| |-- MethodInterceptor (核心:方法拦截器)
|
|-- BeforeAdvice
|-- AfterAdvice
|-- ThrowsAdvice
2. Spring 定义的核心接口
这部分是 Spring 特有的,用于适配和扩展标准 AOP。
2.1 切点 (Pointcut)Pointcut (核心:切点) ^ |-- StaticMethodMatcherPointcut (静态切点:最常用,仅匹配方法签名) | ^ | |-- JdkRegexpMethodPointcut (正则匹配) | |-- AspectJExpressionPointcut (AspectJ 表达式匹配,如 execution(...)) | |-- DynamicMethodMatcherPointcut (动态切点:还要匹配运行时参数)
2.2 切面/通知器 (Advisor)
Spring 中通常不直接叫 Aspect,而是叫 Advisor。一个 Advisor = Pointcut + Advice。
Advisor (核心:通知器)
^
|-- PointcutAdvisor (持有 Pointcut 的 Advisor)
^
|-- AbstractGenericPointcutAdvisor
| ^
| |-- AspectJPointcutAdvisor (集成 AspectJ 注解用的)
| |-- DefaultPointcutAdvisor (最通用的实现)
3. 代理配置与创建体系 (Proxy Creator)
这部分负责如何组装配置,并生成最终的代理对象。
3.1 配置基类 (Config)Advised (接口:定义了对 AOP 配置的操作,如 addAdvice, getAdvisors) ^ |-- AdvisedSupport (核心配置类:持有 TargetSource, Advisor 列表, 接口列表等) ^ |-- ProxyCreatorSupport (增加了 AopProxyFactory 的能力) ^ |-- ProxyFactory (编程式创建代理的工厂) |-- ProxyFactoryBean (XML配置时代常用的 FactoryBean) |-- AbstractAutoProxyCreator (自动代理创建器,BeanPostProcessor 的基类)
3.2 自动代理创建器 (AutoProxyCreator)
这是 Spring Boot / 注解驱动 AOP 的幕后黑手。
BeanPostProcessor (Spring 接口)
^
|-- AbstractAutoProxyCreator
^
|-- AbstractAdvisorAutoProxyCreator
^
|-- DefaultAdvisorAutoProxyCreator (XML 配置常用)
|-- AnnotationAwareAspectJAutoProxyCreator (Spring Boot 默认,处理 @Aspect)
3.3 代理实现 (AopProxy)
真正的代理对象生成器。
AopProxy (接口)
^
|-- JdkDynamicAopProxy (JDK 动态代理实现)
|-- CglibAopProxy (CGLIB 动态代理实现)
4. 总结图谱
原料层:Advice (逻辑), Pointcut (位置) -> 组合成 Advisor。
配置层:AdvisedSupport 把 Advisor、Target、Interfaces 放在一起。
工厂层:ProxyFactory 或 AutoProxyCreator 使用配置信息。
产品层:委托 AopProxy (JDK/CGLIB) 生产出最终的代理对象。