Spring AOP 源码分析:创建代理(一)

Spring AOP 源码分析:创建代理(一)

Spring AOP 源码分析:入门 中,梳理出来了 Spring AOP 的入口。上一篇文章 Spring AOP 源码分析:获得通知 中着重介绍了如何获取通知。接着上一篇文章,这篇文章介绍一下如何创建代理。

AbstractAutoProxyCreator#createProxy
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);

  //如果没有使用CGLib代理
  if (!proxyFactory.isProxyTargetClass()) {
    // 是否可能使用CGLib代理
    // 决定对于给定的 Bean 是否应该使用 targetClass 而不是他的接口代理
    if (shouldProxyTargetClass(beanClass, beanName)) {
      proxyFactory.setProxyTargetClass(true);
    }
    else {
      // 查看beanClass对应的类是否含有InitializingBean.class/DisposableBean.class/Aware.class接口
      // 无则采用JDK动态代理,有则采用CGLib动态代理
      evaluateProxyInterfaces(beanClass, proxyFactory);
    }
  }

  // 获得所有关联的Advisor集合(该分支待补充)
  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  proxyFactory.addAdvisors(advisors);
  // 此处的targetSource一般为SingletonTargetSource
  proxyFactory.setTargetSource(targetSource);
  // 定制代理,扩展点,空实现
  customizeProxyFactory(proxyFactory);

  // 用来控制代理工厂被配置后,是否还允许修改通知
  // 缺省为 false
  proxyFactory.setFrozen(this.freezeProxy);
  // 是否设置预过滤模式,此处针对本文为true
  if (advisorsPreFiltered()) {
    proxyFactory.setPreFiltered(true);
  }

  // 获取使用JDK动态代理或者cglib动态代理产生的对象
  return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory#getProxy(ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
  // 1、创建JDK方式的AOP代理或者CGLib方式的AOP代理
  // 2、调用具体的AopProxy来创建Proxy代理对象
  return createAopProxy().getProxy(classLoader);
}

createAopProxy() 方法中就不再列出,因为 AopProxyFactory 接口只有一个实现类 DefaultAopProxyFactory。所以,直接来看看 getProxy(classLoader) 方法:

DefaultAopProxyFactory#createAopProxy
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // 如果实现接口,默认采用Java动态代理
  // 如果没有接口,或者有接口却强制使用 cglib
  if (!IN_NATIVE_IMAGE &&
    // optimize 是否实用激进的优化策略
    // proxyTargetClass 为 true,则代理类本身而不是接口
    // 是否存在代理接口
    (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.");
    }
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    return new JdkDynamicAopProxy(config);
  }
}

到这里就可以清楚看到

JdkDynamicAopProxy

JdkDynamicAopProxy 类如其名,就是通过 JDK 的动态代理来生成代理类的。对 JDK 动态代理比较熟悉的话,应该清楚:代理类的增强是通过实现 InvocationHandler 接口,在其 invoke 方法中增加增强逻辑。而 JdkDynamicAopProxy 正好实现了 InvocationHandler 接口,所以,在其 invoke 方法中封装了对 AOP 的 Advice(通知/增强) 调用链。

JdkDynamicAopProxy
@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);
  // 调用JDK动态代理方法
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

由于 JdkDynamicAopProxy 实现了 InvocationHandler。所以,重点就是 invoke() 方法。来看一下:

JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Object oldProxy = null;
  boolean setProxyContext = false;

  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;
    // 通过设置 exposeProxy,可以将代理暴露到代理上下文中
    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);

    // Get the interception chain for this method.
    // 获取针对该目标对象的所有增强器(advisor), 这些advisor都是有顺序的,他们会按照顺序进行链式调用
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(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.
    // 检查是否我们有一些通知。如果我们没有,我们可以直接对目标类进行反射调用,避免创建MethodInvocation类
    // 如果没有设定拦截器,那么就直接调用目标类 target 的对应方法
    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...
      //我们需要创建一个方法调用
      // proxy:生成的动态代理对象
      // target:目标方法
      // args: 目标方法参数
      // targetClass:目标类对象
      // chain: AOP拦截器执行链,是一个MethodInterceptor的集合
      MethodInvocation invocation =
          new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
      // Proceed to the joinpoint through the interceptor chain.
      // 通过拦截器链进入连接点
      // 开始执行AOP的拦截过程
      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);
    }
  }
}

从上面高亮代码部分可以看出,增强调用链是在 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass) 方法中组装的。实际上,它是委托给 DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice 方法来完成的。来看一下这个代码:

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
@Override
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.
  // advice适配器注册中心
  // MethodBeforeAdviceAdapter:将Advisor适配成MethodBeforeAdvice
  // AfterReturningAdviceAdapter:将Advisor适配成AfterReturningAdvice
  // ThrowsAdviceAdapter: 将Advisor适配成ThrowsAdvice
  AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  Advisor[] advisors = config.getAdvisors();
  // 返回值集合,里面装的都是Interceptor或者它的子类接口MethodInterceptor
  List<Object> interceptorList = new ArrayList<>(advisors.length);
  // 获取目标类的类型
  Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  // 是否有引介
  Boolean hasIntroductions = null;

  // 去产生代理对象的过程中,针对该目标方法获取到的所有合适的Advisor集合
  for (Advisor advisor : advisors) {
    if (advisor instanceof PointcutAdvisor) {
      // Add it conditionally.
      PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
      // 如果该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) {
          // 将advisor转成MethodInterceptor
          // 从 GlobalAdvisorAdapterRegistry 获得 MethodInterceptor
          MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
          // MethodMatcher接口通过重载定义了两个matches()方法
          // 两个参数的matches() 被称为静态匹配,在匹配条件不是太严格时使用,可以满足大部分场景的使用
          // 称之为静态的主要是区分为三个参数的matches()方法需要在运行时动态的对参数的类型进行匹配
          // 两个方法的分界线就是boolean isRuntime()方法
          // 进行匹配时先用两个参数的matches()方法进行匹配,若匹配成功,则检查boolean isRuntime()的返回值若为
          // true, 则调用三个参数的matches()方法进行匹配(若两个参数的都匹配不中,三个参数的必定匹配不中)

          // 需要根据参数动态匹配(比如重载)
          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;
}

通知的执行则是委托给 ReflectiveMethodInvocation#proceed 来执行的。具体实现如下:

ReflectiveMethodInvocation#proceed
@Override
@Nullable
public Object proceed() throws Throwable {
  // We start with an index of -1 and increment early.
  // 如果执行到链条的末尾, 则直接调用连接点方法 即直接调用目标方法
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return invokeJoinpoint();
  }

  // 获取集合中的MethodInterceptor
  Object interceptorOrInterceptionAdvice =
      this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  // 如果是InterceptorAndDynamicMethodMatcher类型(动态匹配)
  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)) {
      // 如果匹配则直接调用MethodInterceptor的invoke方法
      // 注意这里传入的参数是this,我们下面看一下ReflectiveMethodInvocation的类型
      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方法
    // 传入this即ReflectiveMethodInvocation实例
    // 传入this进入 这样就可以形成一个调用的链条了
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  }
}

ReflectiveMethodInvocation 通过递归调用 proceed() 方法,来实现链式调用的。因为链本身是一个 List 对象,每次递归调用时,只需要推进其下标就可以实现链式调用的效果。

贴代码太多,篇幅有又老长了。关于利用 cglib 创建代理的过程,留到下一篇文章来重点介绍: Spring AOP 源码分析:创建代理(二)