`
huibin
  • 浏览: 741702 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

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以及反射机制对用户定义的拦截器链进行处理。

分享到:
评论

相关推荐

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

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

    Spring源代码解析.rar

    Spring源代码解析7:Spring AOP中对拦截器调用的实现 .doc Spring源代码解析8:Spring驱动Hibernate的实现.doc Spring源代码解析9:Spring Acegi框架鉴权的实现.doc Spring源代码解析10:Spring Acegi框架授权的实现...

    Spring 源代码解析

    Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代码解析9:Spring Acegi框架鉴权的实现 Spring源代码解析10:Spring Acegi框架授权的实现

    Spring源代码解析

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...

    springyuanmaaping.zip

    pring源代码解析1:IOC容器;Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:... Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代

    spring源码分析(1-10)

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...

    spring源码分析

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 8. Spring源代码解析(八):Spring驱动Hibernate的实现 9.Spring源代码解析(九):Spring Acegi框架鉴权的实现 10. Spring源代码解析(十):Spring ...

    Spring源码学习文档,绝对值得好好研究~~

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现.doc Spring源代码解析(八):Spring驱动Hibernate的实现.doc Spring源代码解析(九):Spring Acegi框架鉴权的实现.doc Spring源代码解析(十):Spring ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.5.3.1. RedirectView 13.5.3.2. redirect:前缀 13.5.3.3. forward:...

    Spring中文帮助文档

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. ...

    Spring API

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. ...

    Spring 2.0 开发参考手册

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2....

    spring chm文档

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2....

    Spring面试题

    4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 5.容器提供了众多的辅助类,能加快应用的开发 6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 7.spring属于低侵入...

    Spring in Action(第二版 中文高清版).part2

    11.3.4 使用注释声明拦截器 11.4 小结 第12章 访问企业服务 12.1 从JNDI中获取对象 12.1.1 使用传统的JNDI 12.1.2 注入JNDI对象 12.1.3 在Spring 2中注入JNDI对象 12.2 发送电子邮件 12.2.1 配置邮件发送...

    Spring in Action(第二版 中文高清版).part1

    11.3.4 使用注释声明拦截器 11.4 小结 第12章 访问企业服务 12.1 从JNDI中获取对象 12.1.1 使用传统的JNDI 12.1.2 注入JNDI对象 12.1.3 在Spring 2中注入JNDI对象 12.2 发送电子邮件 12.2.1 配置邮件发送...

    Spring in Action(第2版)中文版

    11.3.4使用注释声明拦截器 11.4小结 第12章访问企业服务 12.1从jndi中获取对象 12.1.1使用传统的jndi 12.1.2注入jndi对象 12.1.3在spring2中注入jndi对象 12.2发送电子邮件 12.2.1配置邮件发送器 12.2.2...

    Spring Security 中文教程.pdf

    1.4.2. 获得源代码 2. Security命名空间配置 2.1. 介绍 2.1.1. 命名空间的设计 2.2. 开始使用安全命名空间配置 2.2.1. 配置web.xml 2.2.2. 最小 &lt;http&gt; 配置 2.2.2.1. auto-config 包含了什么? 2.2...

    spring security 参考手册中文版

    25.1 AOP联盟(MethodInvocation)安全拦截器 197 25.1.1显式MethodSecurityInterceptor配置 197 25.2 AspectJ(JoinPoint)安全拦截器 198 26.基于表达式的访问控制 200 26.1概述 200 26.1.1通用内置表达式 201 ...

Global site tag (gtag.js) - Google Analytics