从底层分析并详解SpringAOP底层实现

首先分析AOP的实现

首先切面(Advisor)由通知(Advice)和切点(Pointcut)组成

包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知

先看一段代码了解一下是aop是怎么运作的

首先定义了两个类实现了MethodInterceptor接口,这里的 MethodInvocation 是对原始方法的包装同时也是AOP通知功能的实现方式。

首先这里method,target,args都是原始对象的方法参数用于反射调用。构造参数中传入集合的是刚刚来两个实现MethodInterceptor的类。

当这里的proceed方法被调用时,会有一个初始化为0的参数,作用是记录这里第几个调用的Advisor,当所有的Advisor调完后就会执行真正的原始方法。从而形成了递归调用,效果就是我们看到的环绕通知

这是主程序加效果

接下来我们看一下Spring如何实现的

实现时要使用@EnableAspectJAutoProxy注解,它的作用是通过封装Import注解导入一些其他类,它导入了 AnnotationAwareAspectJAutoProxyCreator 类

由于此类是被保护的所以我采用继承的方法去调用相关方法,并自定义了一个Advisor,同时还通过注解去引入

复制代码

这是主程序

@Aspect注解的解析

首先这是一个Bean后处理器方法

首先把原始工厂和beanName封装在 MetadataAwareAspectInstanceFactory 类中,此类用于保存@Aspect注解标注的类信息,紧接着调用 this.advisorFactory.getAdvisors 方法

此方法根据类获得方法信息以及注解信息封装为 InstantiationModelAwarePointcutAdvisorImpl 这种类型的Advisor。

Advisor由Advice和切点表达式组成

通过 findEligibleAdvisors 方法获取工厂中所有的Advisor,然后根据bean的类型进行匹配做代理

不过这里值得注意的是导入了一个org.springframework.aop.interceptor.ExposeInvocationInterceptor 这个类,这个类是为了把信息存放在ThreadLocal中暴露给整个线程

顺带说一下这里的wrapIfNecessary就是存放在三级缓存的那个bean代理的创建方法

重点在 wrapIfNecessary 方法,这个方法内部会在 getAdvicesAndAdvisorsForBean 方法中

调用 findEligibleAdvisors 方法

然后调用createProxy方法

重点来了

此方法内部创建一个ProxyFactory对象,他会把传入的Advisor通过装饰器模式把他们转化为实现了MethodInterceptor接口的环绕通知

复制代码
proxyTargetClass 和  exposeProxy 

是@EnableAspectJAutoProxy两个可选项,第一个为false代表默认使用jdk生成动态代理,true的话用Cglib。而exposeProxy为true则代表把生成的代理对象存放在ThreadlocalMap中,这样就可以解决嵌套调用时事务失效的功能。

然后调用getProxy方法生成代理对象

然后我们观察代理对象的代理方法

这里的advised就是ProxyFactory 紧接着调用 getInterceptorsAndDynamicInterceptionAdvice 方法

此方法内部获取所有的Advisor然后进行方法匹配,如果匹配就会把Advice包装为环绕通知

首先获得advice,然后包装

就是这样进行包装,然后通过MethodInvocation获取这些环绕通知,调用invoke这样就可以实现递归嵌套调用,比如前置通知转化为环绕通知后只需要在proceed之前调用就行,就完成了转化

最终调用

就是通过创建 Invocation 然后递归调用

这是官方的proceed实现和我们最开始写的类似

由于上面说了会默认加入一个 ExposeInvocationInterceptor 类用于暴露代理接下来就是证明

这里的invocation就是一个ThreadLocal对象它的作用就是让别的MethodInteceptor也可以使用

就好比通过转化后的 MethodBeforeAdviceInterceptor 就需要用

相关推荐
凯基迪科技34 分钟前
exe软件壳的分类----加密保护壳
java
尘世闲鱼40 分钟前
解数独(C++版本)
开发语言·c++·算法·解数独
wuxuanok1 小时前
Web后端开发-分层解耦
java·笔记·后端·学习
kyle~1 小时前
C/C++字面量
java·c语言·c++
纨妙1 小时前
python打卡day59
开发语言·python
neoooo1 小时前
别慌,Java只有值传递——一次搞懂“为啥我改了它还不变”!
java·后端·spring
秋难降1 小时前
Python 知识 “八股”:给有 C 和 Java 基础的你😁😁😁
java·python·c
wuxuanok1 小时前
Web后端开发-请求响应
java·开发语言·笔记·学习
livemetee2 小时前
spring-ai 1.0.0 (3)交互增强:Advisor 顾问模块
java
DDDDDouble2 小时前
<二>Sping-AI alibaba 入门-记忆聊天及持久化
java·人工智能