Spring(十九):AOP代理——JdkDynamicAopProxy、填坑:AOP代理与上循环依赖

本文详细探讨了Spring AOP中的JdkDynamicAopProxy工作原理,包括如何曝光代理对象以及如何在拦截器链中执行。通过源码分析,解释了拦截器链的执行流程,特别是MethodInvocation的proceed方法。此外,文章还揭示了动态匹配的过程,并介绍了如何通过ThreadLocal存储和获取代理对象。最后,文章着重讨论了AOP在处理循环依赖时的角色,特别是三级缓存如何协同工作以解决这个问题。
摘要由CSDN通过智能技术生成

static Object setCurrentProxy(@Nullable Object proxy) {

//获取旧的曝光的代理对象

Object old = currentProxy.get();

//下面就是对曝光当前的代理对象了

//判断是否为空

if (proxy != null) {

//如果不为空,存放进currentProxy里面

//这样就完成曝光了

currentProxy.set(proxy);

}

else {

//如果为空,代表要曝光个空的代理对象

//只需移除旧的代理对象即可

currentProxy.remove();

}

//返回旧的曝光的代理对象

//并且回归上层是对应oldProxy的

return old;

}

可以看到,代理对象其实被存放在currentProxy里面的

在这里插入图片描述

可以看到CurrentProxt竟然是一个ThreadLocal,Emmmm,这是就明白了具体曝光的操作其实只是将当前的代理对象存放进ThreadLocal里面,猜测是后面执行拦截器链的时候会从ThreadLocal里面拿出来使用,从而让内部方法也能调用到代理对象

拦截器链的执行

对应的部分代码如下

在这里插入图片描述

可以看到,是交由MethodInvocation来进行的

下面就来看看这个proceed方法吧

在这里插入图片描述

拓展一下:这个MethodInvocation里面的实现类有三个,一个是ReflectiveMethodInvocation(对应JDK的代理),另一个是CglibMethodInvocation(对应Cglib代理),另外一个是Anonymous

在这里插入图片描述

还是回归到我们的proceed代码上,源码如下

public Object proceed() throws Throwable {

// We start with an index of -1 and increment early.

//判断是不是已经执行完拦截器链上的方法了

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {

//如果已经执行完,就要去执行切点里面的方法了

return invokeJoinpoint();

}

//去获取当前执行到哪个拦截器了

//说白了就是去获取下一个要执行的拦截器

Object interceptorOrInterceptionAdvice =

this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

//判断当前要执行的拦截器类型

//InterceptorAndDynamicMethhodMatch是增强器

if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

InterceptorAndDynamicMethodMatcher dm =

(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

//获取被代理的对象类型

Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());

//进行动态匹配

if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {

return dm.interceptor.invoke(this);

}

//如果动态匹配失败,递归进行proceed

//不匹配就不执行当前的拦截器

else {

return proceed();

}

}

//如果不是增强器,只是一般的拦截器

else {

// It’s an interceptor, so we just invoke it: The pointcut will have

// been evaluated statically before this object was constructed.

//直接执行即可

return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

}

}

总结一下执行的流程

  • 首先判断是不是已经执行完拦截器链上的所有拦截器了,通过currentInterceptorIndex与拦截器链的长度进行比较

  • 如果已经执行完了,就要去执行切点自身的方法了,使用invokeJoinPoint方法

  • 如果未执行完,通过currentInterceptorIndex+1从拦截器链去获取下一个拦截器

  • 接下来就判断获取的拦截器是增强器还是一般的拦截器了

  • 如果是增强器,则要进行动态匹配,如果动态匹配成功,那就执行匹配的方

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值