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从拦截器链去获取下一个拦截器
-
接下来就判断获取的拦截器是增强器还是一般的拦截器了
-
如果是增强器,则要进行动态匹配,如果动态匹配成功,那就执行匹配的方