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

前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为我们提供AOP功能的;
在 JdkDynamicAopProxy中生成Proxy对象的时候:

Java代码 复制代码
  1. return  Proxy.newProxyInstance(classLoader, proxiedInterfaces,  this );  
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);


这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实现了这个接口,也 就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的invoke方法会被作为回调函数调用,下面我们看看这个方法的实 现:

Java代码 复制代码
  1. public  Object invoke(Object proxy, Method method, Object[] args)  throws  Throwable {   
  2.     MethodInvocation invocation =  null ;   
  3.     Object oldProxy =  null ;   
  4.      boolean  setProxyContext =  false ;   
  5.   
  6.     TargetSource targetSource =  this .advised.targetSource;   
  7.     Class targetClass =  null ;   
  8.     Object target =  null ;   
  9.   
  10.      try  {   
  11.          // Try special rules for equals() method and implementation of the   
  12.          // Advised AOP configuration interface.   
  13.   
  14.          if  (! this .equalsDefined && AopUtils.isEqualsMethod(method)) {   
  15.              // What if equals throws exception!?   
  16.              // This class implements the equals(Object) method itself.   
  17.              return  equals(args[ 0 ]) ? Boolean.TRUE : Boolean.FALSE;   
  18.         }   
  19.          if  (! this .hashCodeDefined && AopUtils.isHashCodeMethod(method)) {   
  20.              // This class implements the hashCode() method itself.   
  21.              return   new  Integer(hashCode());   
  22.         }   
  23.          if  (Advised. class  == method.getDeclaringClass()) {   
  24.              // service invocations on ProxyConfig with the proxy config   
  25.              return  AopUtils.invokeJoinpointUsingReflection( this .advised, method, args);   
  26.         }   
  27.   
  28.         Object retVal =  null ;   
  29.   
  30.          if  ( this .advised.exposeProxy) {   
  31.              // make invocation available if necessary   
  32.             oldProxy = AopContext.setCurrentProxy(proxy);   
  33.             setProxyContext =  true ;   
  34.         }   
  35.   
  36.          // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target,   
  37.          // in case it comes from a pool.   
  38.          // 这里是得到目标对象的地方,当然这个目标对象可 能来自于一个实例池或者是一个简单的JAVA对象   
  39.         target = targetSource.getTarget();   
  40.          if  (target !=  null ) {   
  41.             targetClass = target.getClass();   
  42.         }   
  43.   
  44.          // get the interception chain for this method   
  45.          // 这里获得定义好的拦截器链   
  46.         List chain =  this .advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(   
  47.                  this .advised, proxy, method, targetClass);   
  48.   
  49.          // Check whether we have any advice. If we don't, we can fallback on direct   
  50.          // reflective invocation of the target, and avoid creating a MethodInvocation.   
  51.          // 如果没有设定拦截器,那么我们就直接调用目标的 对应方法   
  52.          if  (chain.isEmpty()) {   
  53.              // We can skip creating a MethodInvocation: just invoke the target directly   
  54.              // Note that the final invoker must be an InvokerInterceptor so we know it does   
  55.              // nothing but a reflective operation on the target, and no hot swapping or fancy proxying   
  56.             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);   
  57.         }   
  58.          else  {   
  59.              // We need to create a method invocation...   
  60.              // invocation = advised.getMethodInvocationFactory().getMethodInvocation(   
  61.              //         proxy, method, targetClass, target, args, chain, advised);   
  62.              // 如果有拦截器的设定,那么需要调用拦截 器之后才调用目标对象的相应方法   
  63.              // 这里通过构造一个 ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类   
  64.             invocation =  new  ReflectiveMethodInvocation(   
  65.                     proxy, target, method, args, targetClass, chain);   
  66.   
  67.              // proceed to the joinpoint through the interceptor chain   
  68.              // 这里通过 ReflectiveMethodInvocation来调用拦截器链和相应的目标方法   
  69.             retVal = invocation.proceed();   
  70.         }   
  71.   
  72.          // massage return value if necessary   
  73.          if  (retVal !=  null  && retVal == target && method.getReturnType().isInstance(proxy)) {   
  74.              // Special case: it returned "this" and the return type of the method is type-compatible   
  75.              // Note that we can't help if the target sets   
  76.              // a reference to itself in another returned object.   
  77.             retVal = proxy;   
  78.         }   
  79.          return  retVal;   
  80.     }   
  81.      finally  {   
  82.          if  (target !=  null  && !targetSource.isStatic()) {   
  83.              // must have come from TargetSource   
  84.             targetSource.releaseTarget(target);   
  85.         }   
  86.   
  87.          if  (setProxyContext) {   
  88.              // restore old proxy   
  89.             AopContext.setCurrentProxy(oldProxy);   
  90.         }   
  91.     }   
  92. }  
    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的方法调用 - 使用反射机制来对目标对象的方法进行调用:

Java代码 复制代码
  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. }  
    public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
        throws Throwable {

        // Use reflection to invoke the method.
        // 利用放射机制得到相应的方法,并且调用invoke
        try {
            if (!Modifier.isPublic(method.getModifiers()) ||
                    !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
                method.setAccessible(true);
            }
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            // Invoked method threw a checked exception.
            // We must rethrow it. The client won't see the interceptor.
            throw ex.getTargetException();
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                    method + "] on target [" + target + "]", ex);
        }
        catch (IllegalAccessException ex) {
            throw new AopInvocationException("Couldn't access method: " + method, ex);
        }
    }


对拦截器链的调用处理是在ReflectiveMethodInvocation里实现的:

Java代码 复制代码
  1. public  Object proceed()  throws  Throwable {   
  2.      //    We start with an index of -1 and increment early.   
  3.      // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截 器已经调用完了,这个currentInterceptorIndex的初始值是0   
  4.      if  ( this .currentInterceptorIndex ==  this .interceptorsAndDynamicMethodMatchers.size()) {   
  5.          return  invokeJoinpoint();   
  6.     }   
  7.   
  8.     Object interceptorOrInterceptionAdvice =   
  9.          this .interceptorsAndDynamicMethodMatchers.get( this .currentInterceptorIndex);   
  10.      if  (interceptorOrInterceptionAdvice  instanceof  InterceptorAndDynamicMethodMatcher) {   
  11.          // Evaluate dynamic method matcher here: static part will already have   
  12.          // been evaluated and found to match.   
  13.          // 这里获得相应的拦截器,如果拦截器可以匹配的上 的话,那就调用拦截器的invoke方法   
  14.         InterceptorAndDynamicMethodMatcher dm =   
  15.             (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;   
  16.          if  (dm.methodMatcher.matches( this .method,  this .targetClass,  this .arguments)) {   
  17.              return  dm.interceptor.invoke(nextInvocation());   
  18.         }   
  19.          else  {   
  20.              // Dynamic matching failed.   
  21.              // Skip this interceptor and invoke the next in the chain.   
  22.              // 如果拦截器匹配不上,那就调用下一个拦 截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法   
  23.              this .currentInterceptorIndex++;   
  24.              return  proceed();   
  25.         }   
  26.     }   
  27.      else  {   
  28.          // It's an interceptor, so we just invoke it: The pointcut will have   
  29.          // been evaluated statically before this object was constructed.   
  30.          return  ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(nextInvocation());   
  31.     }   
  32. }  
    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:

Java代码 复制代码
  1. private  ReflectiveMethodInvocation nextInvocation()  throws  CloneNotSupportedException {   
  2.     ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();   
  3.     invocation.currentInterceptorIndex =  this .currentInterceptorIndex +  1 ;   
  4.     invocation.parent =  this ;   
  5.      return  invocation;   
  6. }  
    private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {
        ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();
        invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;
        invocation.parent = this;
        return invocation;
    }


这里的nextInvocation就已经包含了当前的拦截链的基本信息,我们看到在Interceptor中的实现比如 TransactionInterceptor的实现中:

Java代码 复制代码
  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.    }  
    public Object invoke(final MethodInvocation invocation) throws Throwable {
       ......//这里是TransactionInterceptor插入的事务处理代码,我们会在后面分析事务处理实现的时候进行分析
            try {
                //这里是对配置的拦截器链进行迭代处理的调用
                retVal = invocation.proceed();
            }
       ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理
          else {
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
                        new TransactionCallback() {
                            public Object doInTransaction(TransactionStatus status) {
                                 //这里是TransactionInterceptor插入对事务处理的代码
                                TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
                                //这里是对配置的拦截器链进行迭代处理的调用,接着顺着拦截器进行处理
                                try {                        
                                    return invocation.proceed();
                                }
       ......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理
       }


从上面的分析我们看到了Spring AOP的基本实现,比如Spring怎样得到Proxy,怎样利用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值