4

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

 3 years ago
source link: https://www.diguage.com/post/spring-aop-create-proxy-jdk/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

2020-08-10
Spring AOP 源码分析:创建代理(一)
Figure 1.

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.exposeTargetClassConfigurableListableBeanFactory) 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 源码分析:创建代理(二)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK