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

本文详细解析了Spring AOP中的JdkDynamicAopProxy工作原理,包括拦截器链的执行过程。同时,文章深入探讨了AOP代理在处理Bean创建时的循环依赖问题,特别是三级缓存的角色和EarlyBeanReference的使用,展示了如何在循环依赖场景下确保正确创建和使用代理对象。
摘要由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从拦截器链去获取下一个拦截器

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

  • 如果是增强器,则要进行动态匹配,如果动态匹配成功,那就执行匹配的方法,如果动态匹配失败,递归调用proceed方法,既去寻找下一个拦截器

  • 如果获取的是一般的拦截器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值