Spring Aop 的底层生成代理类i的实现除 jdk的动态代理技术外,还用到了Cglib,不过在封装两者的设计原理上相差不大,只是底层工具不同而已。
本文只分析JdkDynamicAopProxy 是如何为一个目标方法执行织入多个切点,也就是将原本可能需要多个“代理类“实现的业务放到一个代理类中(JdkDynamicAopProxy)完成。
JdkDynamicAopProxy 本身就是一个JDK代理的InvocationHandler,spring 在调用其getProxy()方法返回一个代理类对象时:
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 传入的 Handler 就是this,也就是 一个 JdkDynamicAopProxy 对象。所以代理的业务就在 JdkDynamicAopProxy
的 invoke()方法上。
1 /** 2 * Implementation of <code>InvocationHandler.invoke</code>. 3 * <p>Callers will see exactly the exception thrown by the target, 4 * unless a hook method throws an exception. 5 */ 6 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 7 MethodInvocation invocation; 8 Object oldProxy = null; 9 boolean setProxyContext = false; 10 11 TargetSource targetSource = this.advised.targetSource; 12 Class targetClass = null; 13 Object target = null; 14 15 try { 16 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 17 // The target does not implement the equals(Object) method itself. 18 return equals(args[0]); 19 } 20 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 21 // The target does not implement the hashCode() method itself. 22 return hashCode(); 23 } 24 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 25 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 26 // Service invocations on ProxyConfig with the proxy config... 27 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 28 } 29 30 Object retVal; 31 32 if (this.advised.exposeProxy) { 33 // Make invocation available if necessary. 34 oldProxy = AopContext.setCurrentProxy(proxy); 35 setProxyContext = true; 36 } 37 38 // May be null. Get as late as possible to minimize the time we "own" the target, 39 // in case it comes from a pool. 40 target = targetSource.getTarget(); 41 if (target != null) { 42 targetClass = target.getClass(); 43 } 44 45 // Get the interception chain for this method. 46 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 47 48 // Check whether we have any advice. If we don't, we can fallback on direct 49 // reflective invocation of the target, and avoid creating a MethodInvocation. 50 if (chain.isEmpty()) { 51 // We can skip creating a MethodInvocation: just invoke the target directly 52 // Note that the final invoker must be an InvokerInterceptor so we know it does 53 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. 54 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); 55 } 56 else { 57 // We need to create a method invocation... 58 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 59 // Proceed to the joinpoint through the interceptor chain. 60 retVal = invocation.proceed(); 61 } 62 63 // Massage return value if necessary. 64 if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) && 65 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 66 // Special case: it returned "this" and the return type of the method 67 // is type-compatible. Note that we can't help if the target sets 68 // a reference to itself in another returned object. 69 retVal = proxy; 70 } 71 return retVal; 72 } 73 finally { 74 if (target != null && !targetSource.isStatic()) { 75 // Must have come from TargetSource. 76 targetSource.releaseTarget(target); 77 } 78 if (setProxyContext) { 79 // Restore old proxy. 80 AopContext.setCurrentProxy(oldProxy); 81 } 82 } 83 }
invoke方法中的红色加粗代码就是重点部分:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
该行代码是构建代理链,获取到目标方法需要增强的一系列业务代理对象。
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
通过将目标方法和 多个业务代理对象 创建成一个 ReflectiveMethodInvocation,来实际完成 执行目标方法时执行一些拦截器,也就是代理业务。
retVal = invocation.proceed();
该行代码开始执行代理业务和目标方法。
下面是ReflectiveMethodInvocation 的 proceed方法代码:
1 public Object proceed() throws Throwable { 2 // We start with an index of -1 and increment early. 3 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 4 return invokeJoinpoint(); 5 } 6 7 Object interceptorOrInterceptionAdvice = 8 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 9 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 10 // Evaluate dynamic method matcher here: static part will already have 11 // been evaluated and found to match. 12 InterceptorAndDynamicMethodMatcher dm = 13 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 14 if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { 15 return dm.interceptor.invoke(this); 16 } 17 else { 18 // Dynamic matching failed. 19 // Skip this interceptor and invoke the next in the chain. 20 return proceed(); 21 } 22 } 23 else { 24 // It's an interceptor, so we just invoke it: The pointcut will have 25 // been evaluated statically before this object was constructed. 26 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 27 } 28 }
可以看到proceed()方法通过从interceptorsAndDynamicMethodMatchers(list)集合中取出拦截器,拦截器是在前面创建ReflectiveMethodInvocation对象时传入的chain,
通过判断拦截器集合中所有拦截器是否执行完,未执行完这递归调用proceed()方法,执行完则执行目标方法。
以上就是JdkDynamicAopProxy实现多个拦截器拦截目标方法的动态代理业务。
本人(徐自勉)原创内容,转载请注明出处,作者.