Spring AOP的原理(下)

Spring AOP的原理

1、创建代理对象

在上一篇文章(Spring AOP的原理(上))中已经分析了创建并获取适配当前bean的增强器,如果在匹配切面的过程中,发现适配的切面,那就需要创建代理对象了。

本文接下来分析AbstractAutoProxyCreator的postProcessAfterInitialization方法:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }

    return bean;
}

调用AbstractAutoProxyCreator的wrapIfNecessary方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
        //根据bean获取对应的切面信息,如果不为空,则为该bean创建代理对象
        Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
        // protected static final Object[] DO_NOT_PROXY = null;
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
	        //创建bean的代理对象
            Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
	        //返回代理对象给spring容器,spring容器中是bean的代理对象
            return proxy;
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
	        //返回bean本身给spring容器,而不是代理对象
            return bean;
        }
    } else {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
	    //返回bean本身给spring容器,而不是代理对象
        return bean;
    }
}

创建完的代理对象中有如下信息:

调用AbstractAutoProxyCreator的createProxy方法,设置ProxyFactory创建Proxy需要的一切信息:

protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
    }

	//新建代理工厂
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    //设置工厂代理类
    if (!proxyFactory.isProxyTargetClass()) {
        if (this.shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        } else {
            this.evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    //设置拦截切面
    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    //设置被代理对象(目标对象),目标对象被封装到SingletonTargetSource中了
    proxyFactory.setTargetSource(targetSource);
    this.customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    ClassLoader classLoader = this.getProxyClassLoader();
    if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
        classLoader = ((SmartClassLoader)classLoader).getOriginalClassLoader();
    }
    //创建代理对象
    return proxyFactory.getProxy(classLoader);
}

调用ProxyFactory的getProxy方法:

public Object getProxy(@Nullable ClassLoader classLoader) {
    //先创建AopProxy代理,再获取代理对象。根据目标类是否是接口,AopProxy有jdk动态代理和cglib动态代理
    return this.createAopProxy().getProxy(classLoader);
}

调用ProxyCreatorSupport类的createAopProxy方法:

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        this.activate();
    }

    return this.getAopProxyFactory().createAopProxy(this);
}

调用DefaultAopProxyFactory类的createAopProxy方法创建jdk代理或cglib代理:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
	  //如果目标类是接口,则创建jdk动态代理,否则创建cglib动态代理
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

1.1、通过jdk动态代理创建代理对象

先分析jdk动态代理获取代理对象的源码,接着上面的getProxy方法获取代理对象继续分析。

JdkDynamicAopProxy实现InvocationHandler接口,必然重写invoke方法,通过代理对象调用重写后的目标方法时,就会调用此处重写的invoke方法,在invoke方法中对目标方法进行增强。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

   @Override
   public Object getProxy() {
      return getProxy(ClassUtils.getDefaultClassLoader());
   }

   @Override
   public Object getProxy(@Nullable ClassLoader classLoader) {
      if (logger.isTraceEnabled()) {
         logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
      }
      Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
      findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	  //创建代理对象
      return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
   }

   /**
    * Implementation of {@code InvocationHandler.invoke}.
    * <p>Callers will see exactly the exception thrown by the target,
    * unless a hook method throws an exception.
    */
   @Override
   @Nullable
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      Object oldProxy = null;
      boolean setProxyContext = false;
      //在上面创建代理对象时,已通过代理工厂proxyFactory.setTargetSource(targetSource);将封装目标对象的targetSource保存到AdvisedSupport的targetSource属性了,此处就是获取该属性的值
      TargetSource targetSource = this.advised.targetSource;
      Object target = null;

      try {
         if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
         }
         else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
         }
         else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
         }
         else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
               method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
         }

         Object retVal;

         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);

		 //1、将增强器转换为方法拦截器
         // Get the interception chain for this method.
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

	     //如果拦截器链为空,说明没有真实的增强(advice),仅仅通过反射调用被代理方法
         // 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.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
         }
         else {
            // We need to create a method invocation...
            //将拦截器链chain作为一个参数用于创建MethodInvocation对象,invocation.proceed()中就从chain中依次获取拦截器调用invoke方法
            MethodInvocation invocation =
                  new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
		    //2、通过拦截器链调用连接点joinpoint(即目标方法),对目标方法进行增强
            // Proceed to the joinpoint through the interceptor chain.
            retVal = invocation.proceed();
         }

         // Massage return value if necessary.
         Class<?> returnType = method.getReturnType();
         if (retVal != null && retVal == target &&
               returnType != Object.class && returnType.isInstance(proxy) &&
               !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // 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;
         }
         else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                  "Null return value from advice does not match primitive return type for: " + method);
         }
         return retVal;
      }
      finally {
         if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
         }
         if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
         }
      }
   }

}

1.1.1、将增强器转换为方法拦截器

下面先分析将增强器转换为方法拦截器的getInterceptorsAndDynamicInterceptionAdvice方法。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
   MethodCacheKey cacheKey = new MethodCacheKey(method);
   List<Object> cached = this.methodCache.get(cacheKey);
   if (cached == null) {
      cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
      this.methodCache.put(cacheKey, cached);
   }
   return cached;
}

调用DefaultAdvisorChainFactorygetInterceptorsAndDynamicInterceptionAdvice方法。

public List<Object> 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.
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
   Advisor[] advisors = config.getAdvisors();
   List<Object> interceptorList = new ArrayList<>(advisors.length);
   Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
   Boolean hasIntroductions = null;

   for (Advisor advisor : advisors) {
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         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;
}

根据增强器获取拦截器,调用DefaultAdvisorAdapterRegistrygetInterceptors方法。

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   List<MethodInterceptor> interceptors = new ArrayList<>(3);
   Advice advice = advisor.getAdvice();
   //如果增强器实现了MethodInterceptor接口,则直接转成拦截器,如AspectJAfterAdvice、AspectJAroundAdvice 和AspectJAfterThrowingAdvice
   if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
	    //根据增强器适配器创建拦截器,如AspectJMethodBeforeAdvice和AspectJAfterReturningAdvice
         interceptors.add(adapter.getInterceptor(advisor));
      }
   }
   if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
   }
   return interceptors.toArray(new MethodInterceptor[0]);
}

看一下适配器MethodBeforeAdviceAdaptergetInterceptor方法。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

   @Override
   public boolean supportsAdvice(Advice advice) {
      return (advice instanceof MethodBeforeAdvice);
   }

   @Override
   public MethodInterceptor getInterceptor(Advisor advisor) {
      MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
	  //根据增强器创建拦截器
      return new MethodBeforeAdviceInterceptor(advice);
   }

}

下面就是MethodBeforeAdviceInterceptor拦截器的源码。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
   //持有增强器的引用,增强器作为拦截器的一个实例变量
   private final MethodBeforeAdvice advice;


   /**
    * Create a new MethodBeforeAdviceInterceptor for the given advice.
    * @param advice the MethodBeforeAdvice to wrap
    */
   public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
      Assert.notNull(advice, "Advice must not be null");
      this.advice = advice;
   }

    //在拦截器的invoke方法中会调用增强器的增强方法,同时会调用ReflectiveMethodInvocation的proceed方法来调用目标方法
   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
	  //调用增强器的增强方法
      this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
      //调用ReflectiveMethodInvocation的proceed方法来调用目标方法
      return mi.proceed();
   }

}

至此,将增强器转成拦截器的方法逻辑分析完毕。

1.1.2、根据拦截器对目标方法进行增强

现在回过头来再分析ReflectiveMethodInvocation的proceed方法。

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   // currentInterceptorIndex的初始值为-1,如果该值等于拦截器数组长度减1,说明没有拦截器了,则调用目标方法
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      //通过反射调用目标对象target的目标方法,method.invoke(target, args);
      return invokeJoinpoint();
   }
   //让currentInterceptorIndex自增,获取拦截器数组中的拦截器。拦截器数组是在创建MethodInvocation对象时,通过参数chain拦截器链传进来的。
   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.
      //调用具体拦截器(实现了MethodInterceptor接口)的invoke方法,在invoke方法中会调用增强器的增强方法,
      //同时会调用ReflectiveMethodInvocation的proceed方法来调用目标方法,如AspectJAfterAdvice,既是一个增强器,也是一个拦截器
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

拓展:下面分析@After@AfterReturning@Before@Around等增强方法的原理。

此处以AspectJAfterAdvice的invoke方法为例,AspectJAfterAdvice是@After增强方法对应的增强器,实现了org.aopalliance.intercept.MethodInterceptor接口,因此,AspectJAfterAdvice既是一个增强器,也是一个拦截器。假如切面类中只有一个增强方法,且是@After注解的方法,则拦截器数组中只有一个拦截器,即AspectJAfterAdvice,拦截器数组的长度为1。在上面第一次调用ReflectiveMethodInvocation的proceed方法时,currentInterceptorIndex的值为-1,不等于拦截器数组长度减1,所以获取拦截器数组中第一个拦截器,也是唯一的一个拦截器,即AspectJAfterAdvice,接着调用AspectJAfterAdvice的invoke方法,即下面这个invoke方法。在invoke方法中又调用了ReflectiveMethodInvocation的proceed方法,此时currentInterceptorIndex的值为0,等于拦截器数组长度减1,所以调用目标方法。由于增强方法是放在finally中的,所以无论目标方法是否能够成功返回,都会执行增强方法。这就是@After注解的方法一定会执行的原因。

注意此处的MethodInterceptor接口是org.aopalliance.intercept包下的。

public class AspectJAfterAdvice extends AbstractAspectJAdvice
      implements MethodInterceptor, AfterAdvice, Serializable {

   public AspectJAfterAdvice(
         Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
      super(aspectJBeforeAdviceMethod, pointcut, aif);
   }

   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      try {
         //调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
         return mi.proceed();
      }
      finally {
         //调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
         invokeAdviceMethod(getJoinPointMatch(), null, null);
      }
   }

   @Override
   public boolean isBeforeAdvice() {
      return false;
   }

   @Override
   public boolean isAfterAdvice() {
      return true;
   }

}

在抽象父类AbstractAspectJAdviceinvokeAdviceMethod方法中会调用invokeAdviceMethodWithGivenArgs方法,在该方法中通过反射调用切面类中的增强方法,如下所示:

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
   Object[] actualArgs = args;
   if (this.aspectJAdviceMethod.getParameterCount() == 0) {
      actualArgs = null;
   }
   try {
      ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
      // TODO AopUtils.invokeJoinpointUsingReflection
      // aspectJAdviceMethod是切面类中的增强方法,aspectInstanceFactory.getAspectInstance()是从spring容器中获取切面类对象,通过反射调用切面类中的增强方法
      return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
   }
   catch (IllegalArgumentException ex) {
      throw new AopInvocationException("Mismatch on arguments to advice method [" +
            this.aspectJAdviceMethod + "]; pointcut expression [" +
            this.pointcut.getPointcutExpression() + "]", ex);
   }
   catch (InvocationTargetException ex) {
      throw ex.getTargetException();
   }
}

@AfterReturning注解的增强方法对应的增强器是AfterReturningAdvice ,增强器转换之后的拦截器是AfterReturningAdviceInterceptor,同样实现了MethodInterceptor接口,在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量,其invoke方法如下所示。

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 {
	  //调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
      Object retVal = mi.proceed();
	  //调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
      this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
      return retVal;
   }

}

@Before注解的增强方法对应的增强器是AspectJMethodBeforeAdvice,同样继承了抽象父类AbstractAspectJAdvice,另外实现了MethodBeforeAdvice接口。增强器转换之后的拦截器是MethodBeforeAdviceInterceptor,同样实现了MethodInterceptor接口,在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量,其invoke方法如下所示。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
   //在拦截器中会持有对增强器的引用,即增强器是拦截器的实例变量
   private final MethodBeforeAdvice advice;

   /**
    * Create a new MethodBeforeAdviceInterceptor for the given advice.
    * @param advice the MethodBeforeAdvice to wrap
    */
   public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
      Assert.notNull(advice, "Advice must not be null");
      this.advice = advice;
   }

   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
	  //调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
      this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	  //调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了
      return mi.proceed();
   }

}

对于@Around注解的增强方法,一般通过如下的方式进行使用,需要在环绕通知之间调用ProceedingJoinPoint的proceed()方法,在该方法中最终会调用目标方法。这是环绕通知与其他四种通知不一样的地方,需要手动调用ProceedingJoinPoint的proceed()方法来调用目标方法,而其他四种通知不需要手动调用目标方法。下面分析一下@Around增强方法的原理。

@Around(value="execution表达式" )
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
    //获取目标方法的参数
    String name="";
    Object args[] = pjp.getArgs();
    if(args!=null && args.length>1){
        Object arg=args[0];
        name = (String) arg;
    }
    //实现环绕通知
    Object result = null;
    System.out.println("环绕通知:在目标方法之前执行,比如开启事务");
    if("倚天照海".equals(name)){//可以控制目标方法的执行
        result = pjp.proceed();  //执行目标方法
    }
    System.out.println("环绕通知:在目标方法之后执行,比如提交或回滚事务");
    //返回目标方法执行的结果,可以修改目标方法的执行结果,影响目标方法的返回值
    return  result+"ddd";
}

@Around注解的增强方法对应的增强器是AspectJAroundAdvice,同样继承了抽象父类AbstractAspectJAdvice,另外实现了MethodInterceptor接口,说明AspectJAroundAdvice既是一个增强器,也是一个拦截器。其invoke方法如下所示。

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

   public AspectJAroundAdvice(
         Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
      super(aspectJAroundAdviceMethod, pointcut, aif);
   }

   @Override
   public boolean isBeforeAdvice() {
      return false;
   }

   @Override
   public boolean isAfterAdvice() {
      return false;
   }

   @Override
   protected boolean supportsProceedingJoinPoint() {
      return true;
   }

   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      if (!(mi instanceof ProxyMethodInvocation)) {
         throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
      }
      ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
      ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
      JoinPointMatch jpm = getJoinPointMatch(pmi);
	  //调用增强器的方法,会调用抽象父类AbstractAspectJAdvice的invokeAdviceMethod方法,最终通过反射调用切面类中的增强方法
      return invokeAdviceMethod(pjp, jpm, null, null);
   }

   /**
    * Return the ProceedingJoinPoint for the current invocation,
    * instantiating it lazily if it hasn't been bound to the thread already.
    * @param rmi the current Spring AOP ReflectiveMethodInvocation,
    * which we'll use for attribute binding
    * @return the ProceedingJoinPoint to make available to advice methods
    */
   protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
      return new MethodInvocationProceedingJoinPoint(rmi);
   }

}

通过增强器AspectJAroundAdvice的invoke源码可知,会调用抽象父类AbstractAspectJAdviceinvokeAdviceMethod方法,最终通过反射调用切面类中的增强方法,在@Around注解的增强方法中会调用ProceedingJoinPoint的proceed()方法(这是程序员手动调用的),通过proceed方法调用目标方法。由上面的增强器AspectJAroundAdvice的源码可知,是通过MethodInvocationProceedingJoinPoint创建的ProceedingJoinPoint,它的proceed方法如下所示。

public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {

   private final ProxyMethodInvocation methodInvocation;
   //省略了其他属性和方法
   /**
    * Create a new MethodInvocationProceedingJoinPoint, wrapping the given
    * Spring ProxyMethodInvocation object.
    * @param methodInvocation the Spring ProxyMethodInvocation object
    */
   public MethodInvocationProceedingJoinPoint(ProxyMethodInvocation methodInvocation) {
      Assert.notNull(methodInvocation, "MethodInvocation must not be null");
      this.methodInvocation = methodInvocation;
   }

   @Override
   public Object proceed() throws Throwable {
      //调用ReflectiveMethodInvocation的proceed方法,又回到上面的proceed方法中了,
      //在proceed方法中会调用目标方法,这就是在@Around增强方法中通过proceed方法调用目标方法的原理
      return this.methodInvocation.invocableClone().proceed();
   }

   @Override
   public Object proceed(Object[] arguments) throws Throwable {
      Assert.notNull(arguments, "Argument array passed to proceed cannot be null");
      if (arguments.length != this.methodInvocation.getArguments().length) {
         throw new IllegalArgumentException("Expecting " +
               this.methodInvocation.getArguments().length + " arguments to proceed, " +
               "but was passed " + arguments.length + " arguments");
      }
      this.methodInvocation.setArguments(arguments);
      return this.methodInvocation.invocableClone(arguments).proceed();
   }

}

1.2、通过cglib动态代理创建代理对象

1.2.1、创建代理对象

下面分析cglib动态代理获取代理对象的源码,接着上面的getProxy方法继续分析:

public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    }

    try {
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
        Class<?> proxySuperClass = rootClass;
        int x;
        if (rootClass.getName().contains("$$")) {
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            Class[] var5 = additionalInterfaces;
            int var6 = additionalInterfaces.length;

            for(x = 0; x < var6; ++x) {
                Class<?> additionalInterface = var5[x];
                this.advised.addInterface(additionalInterface);
            }
        }

        this.validateClassIfNecessary(proxySuperClass, classLoader);
	    //Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展
        Enhancer enhancer = this.createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }

        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
	    //获取拦截回调函数,普通AOP采用的回调函数是Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
        Callback[] callbacks = this.getCallbacks(rootClass);
        Class<?>[] types = new Class[callbacks.length];

        for(x = 0; x < types.length; ++x) {
            types[x] = callbacks[x].getClass();
        }

        enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);
	    //创建代理对象
        return this.createProxyClassAndInstance(enhancer, callbacks);
    } catch (IllegalArgumentException | CodeGenerationException var9) {
        throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", var9);
    } catch (Throwable var10) {
        throw new AopConfigException("Unexpected AOP exception", var10);
    }
}

调用CglibAopProxy类的getCallbacks方法获取拦截器数组:

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isFrozen = this.advised.isFrozen();
    boolean isStatic = this.advised.getTargetSource().isStatic();
    // DynamicAdvisedInterceptor 是CglibAopProxy类中的私有静态内部类,实现了MethodInterceptor 接口 
    Callback aopInterceptor = new CglibAopProxy.DynamicAdvisedInterceptor(this.advised);
    Object targetInterceptor;
    if (exposeProxy) {
        targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
    } else {
        targetInterceptor = isStatic ? new CglibAopProxy.StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.DynamicUnadvisedInterceptor(this.advised.getTargetSource());
    }

    Callback targetDispatcher = isStatic ? new CglibAopProxy.StaticDispatcher(this.advised.getTargetSource().getTarget()) : new CglibAopProxy.SerializableNoOp();
    Callback[] mainCallbacks = new Callback[]{aopInterceptor, (Callback)targetInterceptor, new CglibAopProxy.SerializableNoOp(), (Callback)targetDispatcher, this.advisedDispatcher, new CglibAopProxy.EqualsInterceptor(this.advised), new CglibAopProxy.HashCodeInterceptor(this.advised)};
    Callback[] callbacks;
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

        for(int x = 0; x < methods.length; ++x) {
            Method method = methods[x];
	        //将增强器转换为方法拦截器
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
            fixedCallbacks[x] = new CglibAopProxy.FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            this.fixedInterceptorMap.put(method, x);
        }

        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        this.fixedInterceptorOffset = mainCallbacks.length;
    } else {
        callbacks = mainCallbacks;
    }

    return callbacks;
}

创建代理对象:

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
   enhancer.setInterceptDuringConstruction(false);
   //为代理类设置回调对象,即方法拦截器,在代理对象重写的目标方法中会调用拦截器的intercept方法
   enhancer.setCallbacks(callbacks);
   return (this.constructorArgs != null && this.constructorArgTypes != null ?
         enhancer.create(this.constructorArgTypes, this.constructorArgs) :
         enhancer.create());
}

至此,通过cglib创建代理对象的代码就结束了。

1.2.2、代理对象调用重写的目标方法

DynamicAdvisedInterceptor是CglibAopProxy的静态内部类,通过cglib动态代理创建代理对象之后,在代理对象的重写的目标方法中会调用DynamicAdvisedInterceptor的intercept方法。下面看一下DynamicAdvisedInterceptor类的源码:

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
    private final AdvisedSupport advised;

    public DynamicAdvisedInterceptor(AdvisedSupport advised) {
        this.advised = advised;
    }

    //重写MethodInterceptor接口中的intercept方法
    @Nullable
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Object target = null;
        //在上面创建代理对象时,已通过代理工厂proxyFactory.setTargetSource(targetSource);
        //将封装目标对象的targetSource保存到AdvisedSupport的targetSource属性了,此处就是获取该属性的值
        TargetSource targetSource = this.advised.getTargetSource();

        Object var16;
        try {
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            //获取目标对象
            target = targetSource.getTarget();
            Class<?> targetClass = target != null ? target.getClass() : null;
	        //将增强器转换为方法拦截器(如果在一个类的public方法上使用@Transactional注解,在创建该类的bean实例时,
            //会创建该类的代理对象,且此处会获取到TransactionInterceptor拦截器,该拦截器也实现了MethodInterceptor接口)
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            //如果拦截器链为空,说明没有真实的增强(advice),仅仅是对目标方法的反射调用
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
	            //通过反射调用目标方法
                retVal = methodProxy.invoke(target, argsToUse);
            } else {
	            //调用ReflectiveMethodInvocation的proceed方法对目标方法进行增强
                retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
            }

            retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
            var16 = retVal;
        } finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }

            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }

        }

        return var16;
    }

    public boolean equals(@Nullable Object other) {
        return this == other || other instanceof CglibAopProxy.DynamicAdvisedInterceptor && this.advised.equals(((CglibAopProxy.DynamicAdvisedInterceptor)other).advised);
    }

    public int hashCode() {
        return this.advised.hashCode();
    }
}

由此可知,AOP最终是通过DynamicAdvisedInterceptor类来实现对目标类进行增强的。

对AOP原理的流程进行简单总结:

1.在@Configuration类上或启动类上加上@EnableAspectJAutoProxy注解,在容器启动阶段就会加载beanName为internalAutoProxyCreator的AnnotationAwareAspectJAutoProxyCreator保存到beanDefinitionMap中,用于解析@Aspect。AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口,并继承了AbstractAutoProxyCreator抽象类。

2.在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中会调用getCustomTargetSource方法获取自定义目标源,如果针对目标类创建了TargetSource,此处就会提前创建代理对象。除非有需要,否则通常不会针对某个类创建自定义TargetSource,所以在postProcessBeforeInstantiation方法中不会提前创建代理对象。

3.在spring容器初始化bean之后,会调用AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法,在该方法中会获取到所有BeanPostProcessor接口的实现类,并调用postProcessAfterInitialization方法。其中就有专门用于生成AOP代理对象的处理器AnnotationAwareAspectJAutoProxyCreator,但是这个实现类中并没有postProcessAfterInitialization方法,而是调用其父类AbstractAutoProxyCreator中的这个方法。(子类继承父类之后,就会拥有父类中的方法和属性)(spring中AOP代理对象就是从此处开始创建的,另一处创建AOP代理对象是在循环依赖中通过二级缓存singletonFactory创建的)

4.在AbstractAutoProxyCreator的postProcessAfterInitialization方法中,主要做了两件事:获取增强器和创建代理对象。先根据bean获取适配的增强器,如果不为空,则为该bean创建代理对象,将代理对象保存到spring容器中。否则返回目标bean本身保存到spring容器中。

5.获取增强器。在抽象类AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法中,首先获取所有的增强器,其次从所有增强器中获取适配当前bean的增强器。

       5.1.获取所有的增强器

       (1)获取spring容器BeanFactory中所有已注册的beanName;

       (2)判断对应的类是不是切面类,即判断类上是否有@Aspect注解;

       (3)判断切面类中的方法上是否有@Before、@After、@Around等注解,若有,则为每一个方法创建对应的增强器advisor;

     (4)新建的Advisor对象都保存在BeanFactoryAspectJAdvisorsBuilder#advisorsCache中,当AnnotationAwareAspectJAutoProxyCreator拦截bean的创建过程时,从这里面适配是否有切面可用。

       5.2.获取适配当前bean的增强器

       (1)调用AspectJExpressionPointcut的obtainPointcutExpression方法获取expression表达式(获取@Before、@After等注解方法上的表达式信息);

       (2)通过反射获取目标类中的所有方法,循环目标类中的方法与切面类中表达式限定的方法(已封装成增强器)进行比较匹配;

       (3)若匹配成功,则获取所有适配当前bean的增强器。

6.创建代理对象。

       (1)创建代理工厂,设置创建代理对象所需的一些信息,如设置增强器、目标源等;

       (2)如果目标类是接口,则创建jdk动态代理JdkDynamicAopProxy(实现了InvocationHandler接口,重写了invoke方法),否则创建cglib动态代理ObjenesisCglibAopProxy;

       (3)通过jdk动态代理JdkDynamicAopProxy创建代理对象时,将自身作为InvocationHandler传给了Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)方法,所以在代理对象调用重写后的目标方法时,会调用JdkDynamicAopProxy的invoke方法。在invoke方法中将增强器转换为方法拦截器,如果拦截器链为空,则直接通过反射调用目标方法,否则调用ReflectiveMethodInvocation的proceed方法,在proceed方法中会调用拦截器的invoke方法,在invoke方法中会调用增强器的增强方法,同时会调用ReflectiveMethodInvocation的proceed方法,通过反射调用目标方法,对目标方法进行增强。

      (4) 通过cglib动态代理创建代理对象时,通过Enhancer为代理类设置回调对象,即方法拦截器(实现了org.springframework.cglib.proxy.MethodInterceptor接口,重写了intercept方法,如DynamicAdvisedInterceptor),创建代理对象,在代理对象重写的目标方法中会调用拦截器的intercept方法。在拦截器重写的intercept方法中将增强器转换为方法拦截器(实现了org.aopalliance.intercept.MethodInterceptor接口,该接口中是invoke方法),获取拦截器链,如果拦截器链为空,则在拦截器重写的intercept方法中直接调用MethodProxy类的invoke方法,在该方法中通过反射调用目标对象的目标方法,否则调用ReflectiveMethodInvocation的proceed方法对目标方法进行增强。

注意:上面提到了两种方法拦截器,红色字体标记的方法拦截器实现了org.springframework.cglib.proxy.MethodInterceptor接口,重写了intercept方法,而蓝色字体标记的方法拦截器实现了org.aopalliance.intercept.MethodInterceptor接口,该接口中是invoke方法。增强器转换成的拦截器是后者,例如后置增强器AspectJAfterAdvice实现的就是org.aopalliance.intercept.MethodInterceptor接口。

在创建的代理对象中会对目标方法进行重写,在重写后的目标方法中会调用JdkDynamicAopProxy的invoke方法(通过jdk动态代理生成的代理对象),或者调用DynamicAdvisedInterceptor的intercept方法(通过cglib生成的代理对象),在invoke或intercept方法中都会将增强器转成拦截器。如果增强器实现了org.aopalliance.intercept.MethodInterceptor接口,则增强器本身就是一个拦截器,如AspectJAfterAdvice,否则根据增强器创建对应的拦截器,如根据AspectJMethodBeforeAdvice增强器创建的拦截器是MethodBeforeAdviceInterceptor。

Spring AOP @Before @Around @After 等 advice 的执行顺序:

@Around前置→@Before→目标方法→@AfterRunning(如果有异常→@AfterThrowing) →@After→@Around后置(如果目标方法抛出了异常,@Around的后置通知不会执行)

同一个方法被多个Aspect类拦截,如何指定每个 aspect 的执行顺序呢?
 

方法有以下两种,不管采用哪种方法,都是值越小的 aspect 越先执行。

1.实现org.springframework.core.Ordered接口,实现它的getOrder()方法

2.给aspect添加@Order注解,该注解全称为:org.springframework.core.annotation.Order

@Order(5)

@Component

@Aspect

public class Aspect1 {

    // ...

}

@Order(6)

@Component

@Aspect

public class Aspect2 {

    // ...

}

可保证不管在任何情况下, aspect1 中的 advice 总是比 aspect2 中的 advice 先执行。

对于@Around这个advice,不管它有没有返回值,必须要在方法内部调用pjp.proceed();否则,Controller 中的接口将没有机会被执行,从而也导致了 @Before这个advice不会被触发。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值