SpringAOP的实现原理:3、SpringAOP代理完成之后是如何进行调用的?

正常情况下,每个Advisor里面都会包含PointCut和一个 Advice:pointCut用来判断方法和类是否需要被增强,Advice用来给Bean做增强。
调用步骤:
    1、首先CGLib内部会根据方法获取对应的增强器
    2、调用增强器的增强方法,对于MethodInterceptor的增强器,就会调用intercept方法。
        2.1、intercept方法分析。我们分析对于自己写的@Aspect(@Around、@Before、@After 等)对于此拦截器,首先会对这个类下面的增强器与方法进行匹配,选择处理匹配的增强器。
        2.2 如果数量不为0,则构造 CglibMethodInvocation。并进行调用 CglibMethodInvocation的 proceed()方法,里面会按照 代码定义的顺序倒叙执行,例如:先执行@Return中的process()方法,之后再里面里面进行递归的调用。
 
      在前面分析过了AOP是如何发现需要增强的bean,以及如何通过动态代理的方式将进行增强的。
下面我们将来分析对于 CglibAopProxy增强过的Bean是如何进行调用的。在拦截器中做了什么操作。
通过上一篇文章的末尾,我们发现对于增强过的Bean,对于增强的方法默认的拦截器为DynamicAdvisedInterceptor。
下面我们将先来分析一下这个DynamicAdvisedInterceptor这个类。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
   private final AdvisedSupport advised;
   public DynamicAdvisedInterceptor(AdvisedSupport advised) {
      this.advised = advised;
   }
   @Override
   @Nullable
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object oldProxy = null;
      boolean setProxyContext = false;
      Object target = null;
      //实例的来源,对于单例模式,会返回同一个实例。对于原型模式会返回不同的值。      
      //具体详见:  (转载)Spring 为什么需要TargetSource?
      TargetSource targetSource = this.advised.getTargetSource();
      try {
         if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
         }
         // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
         //实例的来源可以来自一个实例的池子,方便进行管理   
         target = targetSource.getTarget();
         Class targetClass = (target != null ? target.getClass() : null);
         //从所有的增强器中获取此方法可以用的增强器  具体详见下面
         List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
         Object retVal;
         // Check whether we only have one InvokerInterceptor: that is,
         // no real advice, but just reflective invocation of the target.
         if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            // 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.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
         }else {
            // We need to create a method invocation...
            //开始调用增强器的逻辑  具体详见下面介绍
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
         }
         retVal = processReturnType(proxy, target, method, retVal);
         return retVal;
      }finally {
         if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
         }
         if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
         }
      }
   }
   @Override
   public boolean equals(Object other) {
      return (this == other ||
            (other instanceof DynamicAdvisedInterceptor &&
                  this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
   }
   /**
    * CGLIB uses this to drive proxy creation.
    */
   @Override
   public int hashCode() {
      return this.advised.hashCode();
   }

    @Nullable
   private static Object processReturnType(
      Object proxy, @Nullable Object target, Method method, @Nullable Object returnValue) {

       // Massage return value if necessary
       if (returnValue != null && returnValue == target &&
         !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
          // Special case: it returned "this". Note that we can't help
          // if the target sets a reference to itself in another returned object.
          returnValue = proxy;
       }
       Class returnType = method.getReturnType();
       if (returnValue == null && returnType != Void.TYPE && returnType.isPrimitive()) {
          throw new AopInvocationException(
            "Null return value from advice does not match primitive return type for: " + method);
       }
       return returnValue;
    }
} 
   

getInterceptorsAndDynamicInterceptionAdvice 方法介绍:如何获取与方法匹配的增强器

public List getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class targetClass) {
   MethodCacheKey cacheKey = new MethodCacheKey(method);
   List cached = this.methodCache.get(cacheKey);
    //先尝试从缓存中获取,如果缓存中没有,则从factory中重新获取,成功之后再做缓存
   if (cached == null) {
      cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
      this.methodCache.put(cacheKey, cached);
   }
   return cached;
}

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice方法
public List getInterceptorsAndDynamicInterceptionAdvice(
      Advised config, Method method, @Nullable Class targetClass) {

   // This is somewhat tricky... We have to process introductions first,
   // but we need to preserve order in the ultimate list.
   //主要作用:从Advisor中获取Advice(增强器)的工具类
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
   Advisor[] advisors = config.getAdvisors();
   List interceptorList = new ArrayList<>(advisors.length);
   Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
   Boolean hasIntroductions = null;
   //循环遍历此Bean所有的advisors,找到所有匹配的增强器,之后封转为MethodInterceptor进行返回。
   for (Advisor advisor : advisors) {
      //对不同的Advisor做处理,目前主要用的就是PointCutAdvisor
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         //先判断类是否匹配,如果类匹配了再判断方法是否匹配,如果都匹配。就要从advisor中获取对应的增强器(advice)并加工处理,最后进行返回
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            boolean match;
            if (mm instanceof IntroductionAwareMethodMatcher) {
               if (hasIntroductions == null) {
                  hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
               }
               match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
            }else {
               match = mm.matches(method, actualClass);
            }
            if (match) {
               MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn't a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }
   return interceptorList;
} 
   
 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    CglibMethodInvocation介绍:这个类主要作用就是对具体增强器的调用,下面就让我们仔细看一下是如何进行多个增强器的调用的。
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
   @Nullable
   private final MethodProxy methodProxy;

   public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
         Object[] arguments, @Nullable Class targetClass,
         List interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

      super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
      // Only use method proxy for public methods not derived from java.lang.Object
      this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
            method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
            !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
            methodProxy : null);
   }

   /**
    * Gives a marginal performance improvement versus using reflection to
    * invoke the target when invoking public methods.
    */
   @Override
   protected Object invokeJoinpoint() throws Throwable {
      if (this.methodProxy != null) {
         return this.methodProxy.invoke(this.target, this.arguments);
      }else {
         return super.invokeJoinpoint();
      }
   }
}

下面我们来分析一下process()方法的执行过程
public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early. 
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }
    //首先拿去第0个增强器。
   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.
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
      if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
         return dm.interceptor.invoke(this);
      }else {
         // Dynamic matching failed.
         // Skip this interceptor and invoke the next in the chain.
         return proceed();
      }
   }else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
      //对于普通的AOP实现、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice、AspectJAroundAdvice、AspectJMethodBeforeAdvice等都会调用此方法。
      //具体执行顺序  详见下图
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
} 
    

 下面下面每个类的invoke方法都会对逻辑进行处理,除了MethodBeforeAdviceInterceptor之外,都会调用MethodInvocation.proceed()方法,也就是递归调用,继续处理下一个增强器,一直处理到没有增强器,最后调用目标方法。之后再进行返回,相当于递归调用,通过将增强器方法排在目标方法的前后进行调用。从而达到Before和After的效果。

    例子:

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

   private final AfterReturningAdvice advice;

   /**
    * Create a new AfterReturningAdviceInterceptor for the given advice.
    * @param advice the AfterReturningAdvice to wrap
    */
   public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
      Assert.notNull(advice, "Advice must not be null");
      this.advice = advice;
   }
   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      Object retVal = mi.proceed();
        //等排在前面的增强器都执行完成之后,最终执行完成目标方法,在返回的时候才调用下面的方法,做完处理之后返回数据。
      this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
      return retVal;
   }
}

 

你可能感兴趣的:(Spring问题,Spring面试,Spring源码解析,java,spring)