美文网首页SpringFramework
Spring AOP(七)细究 CglibAopProxy 类

Spring AOP(七)细究 CglibAopProxy 类

作者: 蓝笔头 | 来源:发表于2019-05-09 12:57 被阅读61次

接着上一篇 Spring AOP(六)细究 JdkDynamicAopProxy 类 ,我们来继续分析 Spring 中 CGLIB 代理对象的生成和如何对方法进行增强处理的逻辑。

回到 DefaultAopProxyFactory 类中的 createAopProxy 方法,我们发现有两个 AOP 代理类,除了 JdkDynamicAopProxy 类还有 ObjenesisCglibAopProxy 类。

为了方便阅读,把上文中的 createAopProxy 方法的代码清单再次贴出来。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // config.isOptimize() 这个属性没有研究过
  // 满足下面三个条件的任意一个
  // 1. 如果 optimize 属性为 ture 
  // 2. 或者 proxyTargetClass 属性为 ture
  // 3. 被代理类没有可代理的接口
  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 动态代理生成的代理类,则使用 JDK 动态代理
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    
    // 使用 CGLIB 动态代理
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    //  使用 JDK 动态代理
    return new JdkDynamicAopProxy(config);
  }
}

源码分析

下面我们就从 ObjenesisCglibAopProxy 类开始分析,ObjenesisCglibAopProxy 类的代码清单如下所示。

class ObjenesisCglibAopProxy extends CglibAopProxy {

  private static final SpringObjenesis objenesis = new SpringObjenesis();
  
  public ObjenesisCglibAopProxy(AdvisedSupport config) {
    super(config);
  }

  @Override
  protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
      // 通过 Objenesis 技术实例化代理对象
  }
  
}

可以看到 ObjenesisCglibAopProxy 中就只有实例化代理对象的方法,getProxy() 方法在其父类 CglibAopProxy 类中定义,代码清单如下所示。

public Object getProxy() {
  return getProxy(null);
}

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

    // CGLIB 代理类通过继承被代理类实现动态代理
    // 1. 获得需要被代理的的类
    Class<?> proxySuperClass = rootClass;
    if (ClassUtils.isCglibProxyClass(rootClass)) {
      // 如果被代理类已经是被 CGLIB 代理过的了,则代理其父类,避免出现 java.lang.ClassFormatError: Duplicate method name "newInstance" 异常
      // 举个例子:rootClass 是 【Spring AOP (三) CGLIB 动态代理】Service 的代理类 Service$$EnhancerByCGLIB$$bdabbd96 ,那么这里的 proxySuperClass 就是 Service 
      proxySuperClass = rootClass.getSuperclass();
      Class<?>[] additionalInterfaces = rootClass.getInterfaces();
      for (Class<?> additionalInterface : additionalInterfaces) {
        // 添加代理类实现的相关接口,addInterface 方法中会对接口做去重处理
        this.advised.addInterface(additionalInterface);
      }
    }

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

    // 2. 配置 CGLIB Enhancer,还记得 【Spring AOP (三) CGLIB 动态代理】 中通过 enhancer  创建代理类的例子吗?
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
      enhancer.setClassLoader(classLoader);
      if (classLoader instanceof SmartClassLoader &&
          ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
        enhancer.setUseCache(false);
      }
    }
    // 设置被代理类为代理类的父类
    enhancer.setSuperclass(proxySuperClass);
    // 设置代理类需要实现的接口
    // AopProxyUtils.completeProxiedInterfaces 方法在 【Spring AOP(六)细研JdkDynamicAopProxy类】中有详细描述,这里就不赘述
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    // 设置 CGLIB 代理类的命名策略
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    // 设置 CGLIB 代理类字节码的默认生成策略
    enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

    // 3. 获取到生成代理类所需的所有 Callback
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
      types[x] = callbacks[x].getClass();
    }
    // 一个 method 只能被一个 Callback 增强处理
    // 4. 存在超过一个 Callback 的情况下,就需要设置 CallbackFilter,用来分配一个 method 由哪个 Callback 增强处理
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // 5. 生成代理类并创建代理类实例。
    return createProxyClassAndInstance(enhancer, callbacks);
  }
  catch (CodeGenerationException | IllegalArgumentException ex) {
    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",
        ex);
  }
  catch (Throwable ex) {
    // TargetSource.getTarget() failed
    throw new AopConfigException("Unexpected AOP exception", ex);
  }
}

接下来分析在 getProxy 方法中一些需要关注的地方。

SpringNamingPolicy 类的代码清单如下所示。

public class SpringNamingPolicy extends DefaultNamingPolicy {

  public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();

  @Override
  protected String getTag() {
    // DefaultNamingPolicy 中返回 ByCGLIB,
    // 所有通过类名我们就可以知道是 Spring 生成的代理类,还是 CGLIB 原生生成的代理类
    return "BySpringCGLIB";
  }

}

DefaultNamingPolicy 类在 Spring AOP (三) CGLIB 动态代理 一文中已经讨论过了,这里就不再赘述。

getCallbacks 的代码清单如下所示。

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

  // 定义一个用于 AOP 调用的 MethodInterceptor (DynamicAdvisedInterceptor)
  Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

  // targetInterceptor 是不对方法做增强处理的 MethodInterceptor,直接在 intercept 调用目标对象的目标方法
  Callback targetInterceptor;
  if (exposeProxy) {
    targetInterceptor = (isStatic ?
        new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
        new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
  }
  else {
    targetInterceptor = (isStatic ?
        new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
        new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
  }

  // 不需要返回 this 的 method,可以用 StaticDispatcher 进行代理,即直接通过 target 对象调用目标方法
  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(),  
      targetDispatcher, 
      // 通过 advised 直接调用 Advised 接口的方法
      this.advisedDispatcher,
      // 专门用来处理 equals 方法的拦截器,和 JdkDynamicAopProxy 类似
      new EqualsInterceptor(this.advised),
      // 专门用来处理 equals 方法的拦截器,和 JdkDynamicAopProxy 类似
      new HashCodeInterceptor(this.advised)
  };

  Callback[] callbacks;

  // 忽略了 isStatic && isFrozen 条件的逻辑处理
    callbacks = mainCallbacks;
  return callbacks;
}

ProxyCallbackFilter 类的代码清单如下所示,我们主要关注 accept 方法。

// CGLIB callback 数组索引常量
private static final int AOP_PROXY = 0;  // DynamicAdvisedInterceptor
private static final int INVOKE_TARGET = 1; // StaticUnadvisedExposedInterceptor或 DynamicUnadvisedExposedInterceptor
private static final int NO_OVERRIDE = 2; // SerializableNoOp
private static final int DISPATCH_TARGET = 3; // StaticDispatcher
private static final int DISPATCH_ADVISED = 4; // AdvisedDispatcher
private static final int INVOKE_EQUALS = 5; // EqualsInterceptor
private static final int INVOKE_HASHCODE = 6; // HashCodeInterceptor

private static class ProxyCallbackFilter implements CallbackFilter {

    private final AdvisedSupport advised;
    /**
     * 实现 CallbackFilter.accept() 以返回我们需要的 Callbacks 数组中的 index 值。
     */
    @Override
    public int accept(Method method) {
    
      // finalize 方法不需要代理类重写
      if (AopUtils.isFinalizeMethod(method)) {
        return NO_OVERRIDE;
      }
      
      // Advised 接口的方法由 AdvisedDispatcher 增强处理,即直接调用 advised 中的对应方法
      if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
          method.getDeclaringClass().isAssignableFrom(Advised.class)) {
        return DISPATCH_ADVISED;
      }
      // equals 方法由 EqualsInterceptor 代理
      if (AopUtils.isEqualsMethod(method)) {
        return INVOKE_EQUALS;
      }
      // hashCode 方法由 HashCodeInterceptor 代理
      if (AopUtils.isHashCodeMethod(method)) {
        return INVOKE_HASHCODE;
      }
      Class<?> targetClass = this.advised.getTargetClass();
      List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      
      // chain 不为空,表示当前 method 需要被增强处理
      boolean haveAdvice = !chain.isEmpty();
      boolean exposeProxy = this.advised.isExposeProxy();
      boolean isStatic = this.advised.getTargetSource().isStatic();
      boolean isFrozen = this.advised.isFrozen();
      if (haveAdvice || !isFrozen) {
        // 如果公开代理,让其在整个拦截器责任链种可见,则必须使用 AOP_PROXY,即 DynamicAdvisedInterceptor
        if (exposeProxy) {
          return AOP_PROXY;
        }
        String key = method.toString();
        // 检查我们是否有固定拦截器来增强当前 method。
        if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
          // 通过 FixedChainStaticTargetInterceptor 对拦截器做特定的优化处理
          int index = this.fixedInterceptorMap.get(key);
          return (index + this.fixedInterceptorOffset);
        }
        else {
          // 否则使用 AOP_PROXY,即 DynamicAdvisedInterceptor
          return AOP_PROXY;
        }
      }
      else {
        // 如果需要暴露代理对象,或者 target 对象是可变的,则通过 StaticUnadvisedExposedInterceptor 代理
        if (exposeProxy || !isStatic) {
          return INVOKE_TARGET;
        }
        
        // 如果当前方法的返回类型是目标对象的类型,则通过 StaticUnadvisedExposedInterceptor 代理
        Class<?> returnType = method.getReturnType();
        if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
          return INVOKE_TARGET;
        }
        else {
          // 否则,通过 StaticDispatcher 进行代理
          return DISPATCH_TARGET;
        }
      }
    }
  }

然后我们重点关注 Spring AOP 的实现逻辑,在 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;
    TargetSource targetSource = this.advised.getTargetSource();
    try {
      if (this.advised.exposeProxy) {
        // 如果需要在拦截器暴露 proxy 对象,则把 proxy 对象添加到 ThreadLocal 中
        oldProxy = AopContext.setCurrentProxy(proxy);
        setProxyContext = true;
      }
       // 获取目标对象和目标对象类型
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);
      
       // 获取此方法的拦截器链,这个方法在【Spring AOP(六)细研JdkDynamicAopProxy类】种已经讨论过了,这里就不赘述了
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      Object retVal;
      
      // 如果拦截器集合为空,说明当前 method 不需要被增强,则通过 methodProxy 直接调用目标对象上的方法
      if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
        retVal = methodProxy.invoke(target, argsToUse);
      }
      else {
        // 创建 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 && !targetSource.isStatic()) {
        targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
        // 把第一次调用 setCurrentProxy 返回的对象,重新设置到 ThreadLocal 中
        AopContext.setCurrentProxy(oldProxy);
      }
    }
  }
}

可以看到 DynamicAdvisedInterceptor 类中的 intercept 方法和 JdkDynamicAopProxy 类的 invoke 方法十分类似。

最后,我们再来看下 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<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

    super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);

    // 仅对非 Object 类的方法使用 methodProxy 进行调用,详见 invokeJoinpoint() 方法
    this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
        method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
        !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
        methodProxy : null);
  }

  /**
   * 重写 ReflectiveMethodInvocation 中通过反射调用目标方法的逻辑
   */
  @Override
  protected Object invokeJoinpoint() throws Throwable {
    if (this.methodProxy != null) {
      return this.methodProxy.invoke(this.target, this.arguments);
    }
    else {
      return super.invokeJoinpoint();
    }
  }
}

CglibMethodInvocation 类继承了 ReflectiveMethodInvocation 类,并且仅重写了其 invokeJoinpoint() 方法,而 proceed 方法在 Spring AOP(六)细究 JdkDynamicAopProxy 类 中已经详细讲解,所以这里就不再赘述。

至此,Spring 中的 CGLIB AOP 代理 就基本说完了。

(正文完)

扩展阅读

喜欢本文的朋友们,欢迎关注微信公众号【程序员小课堂】,阅读更多精彩内容!


程序员小课堂.jpg

相关文章

网友评论

    本文标题:Spring AOP(七)细究 CglibAopProxy 类

    本文链接:https://www.haomeiwen.com/subject/pnhwoqtx.html