Spring中通过cglib方式执行aop目标方法流程解析

原创
2020/05/05 19:05
阅读数 450

了解此文章之前,请先阅读Spring AOP执行流程源码解析Spring中通过JDK代理执行aop目标方法流程解析

这里承接此文Spring AOP执行流程源码解析,解析当Spring满足条件返回cglib代理的时候,Spring是如何生成目标Bean的代理对象以及如何对目标对象的方法进行代理执行的

ObjenesisCglibAopProxy中的构造方法

代码示例 

public ObjenesisCglibAopProxy(AdvisedSupport config) {
   // 此处调用父类构造方法
   super(config);
}

// 父类CglibAopProxy构造方法
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
   Assert.notNull(config, "AdvisedSupport must not be null");
   if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
      throw new AopConfigException("No advisors and no TargetSource specified");
   }
   // 这里将人参config(ProxyFactory类为AdvisedSupport的子类)设置到ObjenesisCglibAopProxy的advised和advisedDispatcher成员变量中
   this.advised = config;
   this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}

CglibAopProxy类中创建并返回CGlib代理对象的方法

代码示例 

@Override
public Object getProxy(ClassLoader classLoader) {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
   }

   try {
      // 获取目标对象的Class
      Class<?> rootClass = this.advised.getTargetClass();
      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

      Class<?> proxySuperClass = rootClass;
      if (ClassUtils.isCglibProxyClass(rootClass)) {
         proxySuperClass = rootClass.getSuperclass();
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      // Validate the class, writing log messages as necessary.
      validateClassIfNecessary(proxySuperClass, classLoader);

      // Configure CGLIB Enhancer...
      // 创建并配置 Enhancer,  Enhancer 是CGLIB 主要的操作类
      Enhancer enhancer = 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
      // 此处很重要,设置了代理对象的一系列回调,里面包含了针对目标方法拦截器的设置(Aop通知的实现时根据MethodInterceptor方法拦截实现的)
      // cglib代理对象通过回调中的方法拦截器使得目标方法的通知执行
      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // 通过 Enhancer 生成代理对象,并设置回调。
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
            this.advised.getTargetClass() + "]: " +
            "Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (IllegalArgumentException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
            this.advised.getTargetClass() + "]: " +
            "Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (Throwable ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

CglibAopProxy类中的getCallbacks方法

代码示例 

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
   // Parameters used for optimisation choices...
   boolean exposeProxy = this.advised.isExposeProxy();
   boolean isFrozen = this.advised.isFrozen();
   boolean isStatic = this.advised.getTargetSource().isStatic();

   // 初始化AOP的方法拦截器DynamicAdvisedInterceptor,将拦截器封装在DynamicAdvisedInterceptor中,他实现了MethodInterceptor接口
   Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

   // 不需要增强,但可能会返回this的方法:
   // 如果targetSource是静态的话(每次getTarget都是同一个对象),使用StaticUnadvisedExposedInterceptor
   // 否则使用DynamicUnadvisedExposedInterceptor。
   Callback targetInterceptor;
   if (exposeProxy) {
      targetInterceptor = isStatic ?
            new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
   }
   // 这里的分支逻辑与上面相同,只不过exposeProxy为false的情况下不会设置AopContext中的currentProxy。
   else {
      targetInterceptor = isStatic ?
            new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
   }

   // Choose a "direct to target" dispatcher (used for
   // unadvised calls to static targets that cannot return this).
   Callback targetDispatcher = isStatic ?
         new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

   // 初始回调类型数组
   Callback[] mainCallbacks = new Callback[] {
         aopInterceptor,  // for normal advice
         targetInterceptor,  // invoke target without considering advice, if optimized
         new SerializableNoOp(),  // no override for methods mapped to this
         targetDispatcher, this.advisedDispatcher,
         new EqualsInterceptor(this.advised),
         new HashCodeInterceptor(this.advised)
   };

   Callback[] callbacks;

   // 如果targetSource为静态并且配置已经冻结(advice不会改变),可以封装到FixedChainStaticTargetInterceptor来拦截调用方法。
   // 其实FixedChainStaticTargetInterceptor里的逻辑就相当于对固定的target每次创建CglibMethodInvocation来实现aop拦截。
   if (isStatic && isFrozen) {
      Method[] methods = rootClass.getMethods();
      Callback[] fixedCallbacks = new Callback[methods.length];
      this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);

      // TODO: small memory optimisation here (can skip creation for methods with no advice)
      for (int x = 0; x < methods.length; x++) {
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
         fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
               chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
         this.fixedInterceptorMap.put(methods[x].toString(), x);
      }

      /// 把mainCallbacks和fixedCallbacks拼起来。
      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;
}

CglibAopProxy类中的内部类DynamicAdvisedInterceptor ,重点关注intercept方法。当代理类的目标方法执行时,就会执行DynamicAdvisedInterceptor的拦截方法intercept,从而执行目标Bean的所有通知方法以及目标方法。

代码示例 

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

   private final AdvisedSupport advised;

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

   @Override
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object oldProxy = null;
      boolean setProxyContext = false;
      Class<?> targetClass = null;
      Object target = null;
      try {
         if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
         }
         // May be null. Get as late as possible to minimize the time we
         // "own" the target, in case it comes from a pool...
         target = getTarget();
         if (target != null) {
            targetClass = target.getClass();
         }
         // 获取目标Bean的所有可用通知方法
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
         Object retVal;
		 // 如果目标Bean没有增强并且方法为public,则直接调用
         if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
         }
         else {
            // 如果目标Bean有可用的通知方法
            // 这里直接初始化CglibMethodInvocation类,并执行了他的proceed方法,进行目标方法的以及通知方法链的调用
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
         }
         retVal = processReturnType(proxy, target, method, retVal);
         return retVal;
      }
      finally {
         if (target != null) {
            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();
   }

   protected Object getTarget() throws Exception {
      return this.advised.getTargetSource().getTarget();
   }

   protected void releaseTarget(Object target) throws Exception {
      this.advised.getTargetSource().releaseTarget(target);
   }
}

CglibAopProxy类中的内部类CglibMethodInvocation ,它是ReflectiveMethodInvocation 的子类,到这里,估计大家对后续的流程也就清楚了。ReflectiveMethodInvocation以及后续通知链的执行详情见Spring中通过JDK代理执行aop目标方法流程解析

代码示例 

private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

   private final MethodProxy methodProxy;

   private final boolean publicMethod;

   public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
         Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
	  // 调用父类ReflectiveMethodInvocation 的构造器方法
      super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
      this.methodProxy = methodProxy;
      this.publicMethod = Modifier.isPublic(method.getModifiers());
   }

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

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部