Spring 源码阅读 58:配置 ProxyFactory 的 Advisor 列表

642 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情

基于 Spring Framework v5.2.6.RELEASE

接上篇:Spring 源码阅读 57:配置 ProxyFactory 的 proxyTargetClass 属性

概述

本文接着上一篇分析 Spring 创建 AOP 代理对象的createProxy方法。之前分析了 ProxyFactory 的创建、基础的配置参数,以及如何通过后处理器的配置和 Bean 类型实现的接口信息,来配置 ProxyFactory 的proxyTargetClass属性,这个属性决定了创建代理对象时是通过 JDK 动态代理的方式创建还是 CGLIB 方式创建。

构建 Advisor 列表

先回到createProxy方法的代码中。

本文开始分析下面的这部分:

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

首先,会调用buildAdvisors方法,构建一个 Advisor 列表,方法中的参数specificInterceptors就是在调用createProxy方法时传入的参数,也就是之前从 Spring 容器中找到的与当前 Bean 对象匹配的增强逻辑的集合。这里为什么还要构建一次 Advisor 的列表呢,我们进入方法查看。

buildAdvisors 方法

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
   // Handle prototypes correctly...
   Advisor[] commonInterceptors = resolveInterceptorNames();

   List<Object> allInterceptors = new ArrayList<>();
   if (specificInterceptors != null) {
      allInterceptors.addAll(Arrays.asList(specificInterceptors));
      if (commonInterceptors.length > 0) {
         if (this.applyCommonInterceptorsFirst) {
            allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
         }
         else {
            allInterceptors.addAll(Arrays.asList(commonInterceptors));
         }
      }
   }
   if (logger.isTraceEnabled()) {
      int nrOfCommonInterceptors = commonInterceptors.length;
      int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
      logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
            " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
   }

   Advisor[] advisors = new Advisor[allInterceptors.size()];
   for (int i = 0; i < allInterceptors.size(); i++) {
      advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
   }
   return advisors;
}

先整体看一下这个方法的流程。首先,通过resolveInterceptorNames方法得到一个 Advisor 列表commonInterceptors,名称翻译过来就是普通拦截器。然后,将commonInterceptorsspecificInterceptors都添加到实现声明的allInterceptors。最后,遍历allInterceptors中的元素,通过调用成员变量advisorAdapterRegistrywrap方法处理成 Advisor 对象后,得到方法最终的结果。

接下来详细分析,先进入resolveInterceptorNames方法查看。

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#resolveInterceptorNames
private Advisor[] resolveInterceptorNames() {
   BeanFactory bf = this.beanFactory;
   ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
   List<Advisor> advisors = new ArrayList<>();
   for (String beanName : this.interceptorNames) {
      if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
         Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
         Object next = bf.getBean(beanName);
         advisors.add(this.advisorAdapterRegistry.wrap(next));
      }
   }
   return advisors.toArray(new Advisor[0]);
}

这个方法中,会根据interceptorNames成员变量中保存的每一个拦截器名称,找到容器中对应的 Bean 实例,经过advisorAdapterRegistrywrap方法的处理,得到最终返回的 Advisor 列表。

再看一下interceptorNames里有什么:

 /** Default is no common interceptors. */
private String[] interceptorNames = new String[0];

可以看到,默认情况下这个数组是空的,并且advisorAdapterRegistrywrap方法我们后面还会分析到,所以resolveInterceptorNames方法就分析到这里。

回到buildAdvisors方法中,接着往下看。

接下来,会将commonInterceptorsspecificInterceptors合并为一个allInterceptors列表,合并时会进行判断,如果成员变量applyCommonInterceptorsFirst的值时true,则将commonInterceptors添加到allInterceptors头部,否则添加到尾部。这个属性的默认值是true

方法的最后,会通过成员变量advisorAdapterRegistrywrap方法来处理allInterceptors里的每一个拦截器。

advisorAdapterRegistry.wrap 方法

我们进入wrap方法。

@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
   if (adviceObject instanceof Advisor) {
      return (Advisor) adviceObject;
   }
   if (!(adviceObject instanceof Advice)) {
      throw new UnknownAdviceTypeException(adviceObject);
   }
   Advice advice = (Advice) adviceObject;
   if (advice instanceof MethodInterceptor) {
      // So well-known it doesn't even need an adapter.
      return new DefaultPointcutAdvisor(advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      // Check that it is supported.
      if (adapter.supportsAdvice(advice)) {
         return new DefaultPointcutAdvisor(advice);
      }
   }
   throw new UnknownAdviceTypeException(advice);
}

这个方法的逻辑比较简单,作用是将参数传入的拦截器对象(也就是上一步allInterceptors集合中的每一个元素)封装成 Advisor 对象。

如果当前操作的拦截器类型本身就是 Advisor 的实现类,那么,将其原样返回即可。如果它不是 Advisor 的实现类,那么在判断它是否是 Advice 的实现类,如果不是,则抛出异常,也就是说,它只能是 Advisor 或者 Advice 的实现类。

之后就是 Advice 的情况。先判断它是不是 MethodInterceptor 的实现类,MethodInterceptor 是 Advice 的子接口,如果是 MethodInterceptor 的实现类的话,则将其封装为 DefaultPointcutAdvisor 返回。

最后,对于是 Advice 实现类,但不是 MethodInterceptor 实现类的情况,在进行下面的逻辑处理。

遍历adapters成员变量中的每一个元素adapteradapters中的内容可以从以下代码中看到:

private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {
   registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
   registerAdvisorAdapter(new AfterReturningAdviceAdapter());
   registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
   this.adapters.add(adapter);
}

初始状态下,这里有三个 Advice 适配器。在遍历过程中对正在处理的 Advice 类型的拦截器,调用adaptersupportsAdvice方法,判断遍历到的适配器是不是与当前的拦截器适配,如果得到结果true,则将拦截器封装为 DefaultPointcutAdvisor 返回。如果adapters中没有能够预知适配的适配器,则表示无法将当前的拦截器包装成 Advisor,会在wrap方法的最后抛出异常。

其实适配器的supportsAdvice方法就是判断拦截器的类型。

介绍完wrap方法,buildAdvisors方法的全部流程也就介绍完了。在createProxy方法中,buildAdvisors的结果会被添加到proxyFactoryadvisors结合中。

接下来,还将目标类型targetSource赋值给了proxyFactory的相应属性。

customizeProxyFactory 方法

设置完advisorstargetSource属性之后,执行了customizeProxyFactory方法。但这个方法是一个空方法。

protected void customizeProxyFactory(ProxyFactory proxyFactory) {
}

可以看出来,这是一个扩展点,通过在子类中重写这个方法,可以在 ProxyFactory 工厂对象的重要属性都配置完之后,在对其进行自定义的处理。

后续的步骤

接下来再看下一个代码片段。

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
   proxyFactory.setPreFiltered(true);
}

这里又给proxyFactory配置了两个属性,其中if语句的判断条件中advisorsPreFiltered需要留意。

// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#advisorsPreFiltered
protected boolean advisorsPreFiltered() {
   return false;
}

在 AbstractAutoProxyCreator 中,这个方法返回了false。但是,我们这里用到的创建 AOP 代理的后处理器,并不是 AbstractAutoProxyCreator 类型,而是它的子类,所以需要找到子类中与具体实现类关系最近的类中的方法实现。可以找到 AbstractAdvisorAutoProxyCreator 找到重写的方法实现,返回的是true

// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#advisorsPreFiltered
@Override
protected boolean advisorsPreFiltered() {
   return true;
}

createProxy方法的最后,返回了通过调用proxyFactory的getProxy方法创建的代理对象。

return proxyFactory.getProxy(getProxyClassLoader());

具体的创建代理对象的原理,放到下篇文章中分析。

总结

本文分析了 Spring 创建 AOP 代理对象之前,初始化 ProxyFactory 对象的最后一部分逻辑,主要包含 Advisor 列表的构建。至此,可以看出,ProxyFactory 创建代理对象之前,最重要的配置内容就是创建代理对象的方式(JDK 动态代理或 CGLIB)以及增强逻辑的集合,接下来就进入了最后创建代理对象的过程。