Spring源代码解析(七):Spring AOP中对拦截器调用的实现

前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为我们提供AOP功能的;
在JdkDynamicAopProxy中生成Proxy对象的时候:
  1. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 
这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实现了这个接口,也就是说当 Proxy对象的函数被调用的时候,这个InvocationHandler的invoke方法会被作为回调函数调用,下面我们看看这个方法的实现:
# public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
#    MethodInvocation invocation = null; 
#    Object oldProxy = null; 
#    boolean setProxyContext = false; 

#    TargetSource targetSource = this.advised.targetSource; 
#    Class targetClass = null; 
#    Object target = null; 

#    try { 
#        // Try special rules for equals() method and implementation of the 
#        // Advised AOP configuration interface. 

#        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 
#            // What if equals throws exception!? 
#            // This class implements the equals(Object) method itself. 
#            return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE; 
#        } 
#        if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 
#            // This class implements the hashCode() method itself. 
#            return new Integer(hashCode()); 
#        } 
#        if (Advised.class == method.getDeclaringClass()) { 
#            // service invocations on ProxyConfig with the proxy config 
#            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 
#        } 

#        Object retVal = null; 

#        if (this.advised.exposeProxy) { 
#            // make invocation available if necessary 
#            oldProxy = AopContext.setCurrentProxy(proxy); 
#            setProxyContext = true; 
#        } 

#        // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target, 
#        // in case it comes from a pool. 
#        // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例池或者是一个简单的JAVA对象 
#        target = targetSource.getTarget(); 
#        if (target != null) { 
#            targetClass = target.getClass(); 
#        } 

#        // get the interception chain for this method 
#        // 这里获得定义好的拦截器链 
#        List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( 
#                this.advised, proxy, method, targetClass); 

#        // Check whether we have any advice. If we don't, we can fallback on direct 
#        // reflective invocation of the target, and avoid creating a MethodInvocation. 
#        // 如果没有设定拦截器,那么我们就直接调用目标的对应方法 
#        if (chain.isEmpty()) { 
#            // We can skip creating a MethodInvocation: just invoke the target directly 
#            // Note that the final invoker must be an InvokerInterceptor so we know it does 
#            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying 
#            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); 
#        } 
#        else { 
#            // We need to create a method invocation... 
#            // invocation = advised.getMethodInvocationFactory().getMethodInvocation( 
#            //        proxy, method, targetClass, target, args, chain, advised); 
#            // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法 
#            // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类 
#            invocation = new ReflectiveMethodInvocation( 
#                    proxy, target, method, args, targetClass, chain); 

#            // proceed to the joinpoint through the interceptor chain 
#            // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的目标方法 
#            retVal = invocation.proceed(); 
#        } 

#        // massage return value if necessary 
#        if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) { 
#            // Special case: it returned "this" and the return type of the method is type-compatible 
#            // Note that we can't help if the target sets 
#            // a reference to itself in another returned object. 
#            retVal = proxy; 
#        } 
#        return retVal; 
#    } 
#    finally { 
#        if (target != null && !targetSource.isStatic()) { 
#            // must have come from TargetSource 
#            targetSource.releaseTarget(target); 
#        } 

#        if (setProxyContext) { 
#            // restore old proxy 
#            AopContext.setCurrentProxy(oldProxy); 
#        } 
#    } 
# }
我们先看看目标对象方法的调用,这里是通过AopUtils的方法调用 - 使用反射机制来对目标对象的方法进行调用:
  1. public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) 
  2.    throws Throwable { 
  3. 
  4.    // Use reflection to invoke the method. 
  5.    // 利用放射机制得到相应的方法,并且调用invoke 
  6.    try { 
  7.        if (!Modifier.isPublic(method.getModifiers()) || 
  8.                !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { 
  9.            method.setAccessible(true); 
  10.        } 
  11.        return method.invoke(target, args); 
  12.    } 
  13.    catch (InvocationTargetException ex) { 
  14.        // Invoked method threw a checked exception. 
  15.        // We must rethrow it. The client won't see the interceptor. 
  16.        throw ex.getTargetException(); 
  17.    } 
  18.    catch (IllegalArgumentException ex) { 
  19.        throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + 
  20.                method + "] on target [" + target + "]", ex); 
  21.    } 
  22.    catch (IllegalAccessException ex) { 
  23.        throw new AopInvocationException("Couldn't access method: " + method, ex); 
  24.    } 
  25. } 
对拦截器链的调用处理是在ReflectiveMethodInvocation里实现的:
# public Object proceed() throws Throwable { 
#    //    We start with an index of -1 and increment early. 
#    // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完了,这个currentInterceptorIndex的初始值是0 
#    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) { 
#        return invokeJoinpoint(); 
#    } 

#    Object interceptorOrInterceptionAdvice = 
#        this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex); 
#    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 
#        // Evaluate dynamic method matcher here: static part will already have 
#        // been evaluated and found to match. 
#        // 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦截器的invoke方法 
#        InterceptorAndDynamicMethodMatcher dm = 
#            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 
#        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { 
#            return dm.interceptor.invoke(nextInvocation()); 
#        } 
#        else { 
#            // Dynamic matching failed. 
#            // Skip this interceptor and invoke the next in the chain. 
#            // 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法 
#            this.currentInterceptorIndex++; 
#            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(nextInvocation()); 
#    } 
# }
这里把当前的拦截器链以及在拦截器链的位置标志都clone到一个MethodInvocation对象了,作用是当前的拦截器执行完之后,会继续沿着得到这个拦截器链执行下面的拦截行为,也就是会迭代的调用上面这个proceed:
# private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException { 
#    ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone(); 
#    invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1; 
#    invocation.parent = this; 
#    return invocation; 
# }
这里的nextInvocation就已经包含了当前的拦截链的基本信息,我们看到在Interceptor中的实现比如TransactionInterceptor的实现中:
  1. public Object invoke(final MethodInvocation invocation) throws Throwable { 
  2.    ......//这里是TransactionInterceptor插入的事务处理代码,我们会在后面分析事务处理实现的时候进行分析 
  3.        try { 
  4.            //这里是对配置的拦截器链进行迭代处理的调用 
  5.            retVal = invocation.proceed(); 
  6.        } 
  7.    ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理 
  8.      else { 
  9.        try { 
  10.            Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr, 
  11.                    new TransactionCallback() { 
  12.                        public Object doInTransaction(TransactionStatus status) { 
  13.                              //这里是TransactionInterceptor插入对事务处理的代码 
  14.                            TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status); 
  15.                            //这里是对配置的拦截器链进行迭代处理的调用,接着顺着拦截器进行处理 
  16.                            try {                         
  17.                                return invocation.proceed(); 
  18.                            } 
  19.    ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理 
  20.    } 
从上面的分析我们看到了Spring AOP的基本实现,比如Spring怎样得到Proxy,怎样利用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。