接上文 Spring AOP原理之建立AopProxy代理对象
在Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调来完成的。如果使用
JDK的Proxy
来生成代理对象,那么需要通过InvocationHandler来设置拦截器回调.而如果使用CGLIB
来生成代理对象,就需要根据CGLIB的使用要求.通过DynamicAdvisedlnterceptor来完成回调。
JdkDynamicAopProxy的invoke拦截
上篇文章中,在JdkDynamicAopProxy
生成代理对象的时候,我们可以看到这样的源码:
//调用JDK生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
这里的this
参数对应的是InvocationHandler
对象,InvocationHandler
是JDK
定义的反射类的一个接口,这个接口定义了invoke方法。
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
而这个invoke
方法是作为JDK Proxy
代理对象进行拦截的回调入口出现的。在JdkDynamicAopProxy
中实现TlnvocationHandler
接口,也就是说当Proxy
对象的代理方法被调用时.JdkDynamicAopProxy
的invoke
方法作为Proxy
对象的回调函数被触发,从而通过invoke的其体实现。来完成对目标对象方法调用的拦截或者说功能增强的工作。
JdkDynamicAopProxy实现的该方法如下:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; Object var13; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { //如果目标对象没有实现Object类的基本方法:equals Boolean var19 = this.equals(args[0]); return var19; } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { //如果目标对象没有实现Object类的基本方法:hashCode Integer var18 = this.hashCode(); return var18; } if (method.getDeclaringClass() == DecoratingProxy.class) { // Class var17 = AopProxyUtils.ultimateTargetClass(this.advised); return var17; } Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { //根据代理对象的配置来调用服务 retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); return retVal; } if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //得到目标对象 target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
//获得定义好的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果没有设置拦截器,那么久直接调用target的对应方法
if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //如果有定义拦截器,就先调用拦截器之后,再调用目标对象的对应方法 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //沿着拦截器继续前进 retVal = invocation.proceed(); }
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method); } var13 = retVal;
} finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); }
if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); }
}
return var13;
}
对Proxy
对象的代理设里是在invoke
方法中完成的.这些设里包括获取目标对象、拦截器链.同时把这些对象作为愉入,创建了ReflectiveMethodlnvocation
对象,通过这个ReflectiveMethodlnvocation
对象来完成对AOP
功能实现的封装。在这个invoke
方法中,包含了一个完整的拦截器链对目标对象的拦截过程。比如获得拦截器链并对拦截器链中的拦截器进行配置,逐个运行拦截器链里的拦截增强,直到最后对目标对象方法的运行等。
CglibAopProxy的intercept拦截
CgIibAopProxy
的intercept
回调方法的实现和JdkDynamicAopProxy
的回调实现是非常类似的,只是在CghibAopProxy
中构造DynamicAdvisedInterceptor
对象来完成拦截器链的调用,而在JdkDynamicAopProxy
中是通过构造ReflectiveMethodInvocation
对象来完成这个功能的。
DynamicAdvisedInterceptor
通过实现MethodInterceptor
接口来完成:
import java.lang.reflect.Method;
public interface MethodInterceptor extends Callback {
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
其实现如下:
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Object target = null; TargetSource targetSource = this.advised.getTargetSource(); Object var16; try { if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //得到目标对象 target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
//从advised中取得配置好的AOP通知
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果没有AOP遨知配里。那么直接调用target对象的调用方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { //通过CglibMethodlnvocation来启动advice通知 retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed(); } retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
var16 = retVal;
} finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); }
if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); }
}
return var16;
}
从上面可以看出,拦截器的实现逻辑是一样的。包括目标对象的调用,AOP拦截器链的调用以及配置通知器等。