死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读。

Spring 版本:5.1.14.RELEASE

在开始阅读 Spring AOP 源码之前,需要对 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章导读》 这一系列文章

了解 AOP 相关术语,可先查看 《Spring AOP 常见面试题) 》 这篇文章

该系列其他文章请查看:《死磕 Spring 之 AOP 篇 - 文章导读》

在前面的《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:

  1. 筛选出能够应用于当前 Bean 的 Advisor
  2. 找到了合适 Advisor 则创建一个代理对象, JDK 动态代理或者 CGLIB 动态代理

上一篇《Spring AOP 自动代理(二)筛选合适的通知器》文章分析了上面第 1 步的处理过程,先去解析出当前 IoC 容器所有 Advisor 对象,包括 Advisor 类型的 Bean 和从 @AspectJ 注解的 Bean 解析出来的 Advisor 对象;然后通过通过 ClassFilter 类过滤器和 MethodMatcher 方法匹配器筛选出能够应用于这个 Bean 的 Advisor 们,最后进行排序;不同的 AspectJ 根据 @Order 排序,同一个 AspectJ 中不同 Advisor 的排序,优先级:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice

本文将会分析上面的第 2 的创建过程,如果这个 Bean 有合适的 Advisor,那么为这个 Bean 创建一个代理对象,我们一起来看看是如何创建代理对象的。

回顾

// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    /*
     * <1> 如果当前 Bean 已经创建过自定义 TargetSource 对象
     * 表示在上面的**实例化前置处理**中已经创建代理对象,那么直接返回这个对象
     */
    if (StringUtils.hasLength(beanName)
            && this.targetSourcedBeans.contains(beanName))
    {
        return bean;
    }
    // <2> `advisedBeans` 保存了这个 Bean 没有必要创建代理对象,则直接返回
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    /*
     * <3> 不需要创建代理对象,则直接返回当前 Bean
     */
    if (isInfrastructureClass(bean.getClass()) // 如果是 Spring 内部的 Bean(Advice、Pointcut、Advisor 或者 AopInfrastructureBean 标记接口)
            || shouldSkip(bean.getClass(), beanName)) // 应该跳过
    {
        // 将这个 Bean 不需要创建代理对象的结果保存起来
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // <4> 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // <5> 如果有 Advisor,则进行下面的动态代理创建过程
    if (specificInterceptors != DO_NOT_PROXY) {
        // <5.1> 将这个 Bean 已创建代理对象的结果保存至 `advisedBeans`
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // <5.2> 创建代理对象,JDK 动态代理或者 CGLIB 动态代理
        // 这里传入的是 SingletonTargetSource 对象,可获取代理对象的目标对象(当前 Bean)
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // <5.3> 将代理对象的 Class 对象(目标类的子类)保存
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // <5.4> 返回代理对象
        return proxy;
    }

    // <6> 否则,将这个 Bean 不需要创建代理对象的结果保存起来
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    // <7> 返回这个 Bean 对象
    return bean;
}

在创建代理对象的过程中,上面方法的第 4 步尝试获取能够应用于当前 Bean 的 Advisor,该过程在上一篇文章中进行分析过,如果有 Advisor,则调用 createProxy(..) 方法创建代理对象

注意,这里传入的 TargetSource 是一个 SingletonTargetSource 对象,可获取目标对象,如下:

public class SingletonTargetSource implements TargetSource, Serializable {
	private static final long serialVersionUID = 9031246629662423738L;

	private final Object target;

	public SingletonTargetSource(Object target) {
		Assert.notNull(target, "Target object must not be null");
		this.target = target;
	}

	@Override
	public Class<?> getTargetClass() {
		return this.target.getClass();
	}

	@Override
	public Object getTarget() {
		return this.target;
	}

	@Override
	public void releaseTarget(Object target) {
		// nothing to do
	}

	@Override
	public boolean isStatic() {
		return true;
	}
}

创建代理对象的流程

  1. 创建一个 ProxyFactory 代理工厂对象,设置需要创建的代理类的配置信息,例如 Advisor 数组和 TargetSource 目标类来源

  2. 借助 DefaultAopProxyFactory 选择 JdkDynamicAopProxy(JDK 动态代理)还是 ObjenesisCglibAopProxy(CGLIB 动态代理)

    • proxy-target-classfalse 时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理

    • 如果为 true,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理

  3. 通过 JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy 创建一个代理对象

    • JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的 Proxy.newProxyInstance(..) 创建代理对象
    • ObjenesisCglibAopProxy 借助 CGLIB 的 Enhancer 创建代理对象,会设置 Callback 数组和 CallbackFilter 筛选器(选择合适 Callback 处理对应的方法),整个过程相比于 JDK 动态代理更复杂点,主要的实现在 DynamicAdvisedInterceptor 方法拦截器中

AbstractAutoProxyCreator

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator:AOP 自动代理的抽象类,完成主要的逻辑实现,提供一些骨架方法交由子类完成

1. createProxy 方法

createProxy(..) 方法,为目标对象创建一个代理对象,如下:

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
        @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        // 为目标 Bean 的 BeanDefinition 对象设置一个属性
        // org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass -> 目标 Bean 的 Class 对象
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // <1> 创建一个代理工厂
    ProxyFactory proxyFactory = new ProxyFactory();
    // <2> 复制当前 ProxyConfig 的一些属性(例如 proxyTargetClass、exposeProxy)
    proxyFactory.copyFrom(this);

    /**
     * <3> 判断是否类代理,也就是是否开启 CGLIB 代理
     * 默认配置下为 `false`,参考 {@link org.springframework.context.annotation.EnableAspectJAutoProxy}
     */
    if (!proxyFactory.isProxyTargetClass()) {
        /*
         * <3.1> 如果这个 Bean 配置了进行类代理,则设置为 `proxyTargetClass` 为 `true`
         */
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            /*
             * <3.2> 检测当前 Bean 实现的接口是否包含可代理的接口
             * 如没有实现,则将 `proxyTargetClass` 设为 `true`,表示需要进行 CGLIB 提升
             */
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    /*
     * <4> 对入参的 Advisor 进一步处理,因为其中可能还存在 Advice 类型,需要将他们包装成 DefaultPointcutAdvisor 对象
     * 如果配置了 `interceptorNames` 拦截器,也会添加进来
     */
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // <5> 代理工厂添加 Advisor 数组
    proxyFactory.addAdvisors(advisors);
    // <6> 代理工厂设置 TargetSource 对象
    proxyFactory.setTargetSource(targetSource);
    // <7> 对 ProxyFactory 进行加工处理,抽象方法,目前没有子类实现
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    // <8> 是否这个 AdvisedSupport 配置管理器已经过滤过目标类(默认为 false)
    if (advisorsPreFiltered()) {
        // 设置 `preFiltered` 为 `true`
        // 这样 Advisor 们就不会根据 ClassFilter 进行过滤了,而直接通过 MethodMatcher 判断是否处理被拦截方法
        proxyFactory.setPreFiltered(true);
    }

    // <9> 通过 ProxyFactory 代理工厂创建代理对象
    return proxyFactory.getProxy(getProxyClassLoader());
}

该方法的处理过程如下:

  1. 创建一个 ProxyFactory 代理工厂 proxyFactory
  2. 复制当前对象的一些属性给 proxyFactory(例如 proxyTargetClass、exposeProxy),当前 AbstractAutoProxyCreator 对象继承了 ProxyConfig
  3. 判断是否类代理,也就是是否开启 CGLIB 代理,默认配置下为 false,如果没有的话,进行下面处理
    1. 如果这个 Bean 配置了进行类代理,则设置为 proxyTargetClasstrue
    2. 否则,检测当前 Bean 实现的接口是否包含可代理的接口,如没有实现,则将 proxyTargetClass 设为 true,表示需要进行 CGLIB 提升
  4. 调用 buildAdvisors(..) 方法,对入参的 Advisor 数组进一步处理,会将不是 Advisor 类型的对象包装成 DefaultPointcutAdvisor 对象
  5. proxyFactory 代理工厂添加 Advisor 数组
  6. proxyFactory 代理工厂设置 TargetSource 对象,用户获取目标对象
  7. proxyFactory 进行加工处理,抽象方法,目前没有子类实现
  8. 是否这个 AdvisedSupport 配置管理器已经过滤过目标类(默认为 false
    1. 是的话设置 preFilteredtrue,这样 Advisor 们就不会根据 ClassFilter 进行过滤了,而直接通过 MethodMatcher 判断是否处理被拦截方法
  9. 调用 proxyFactory 代理工厂的 getProxy(@Nullable ClassLoader classLoader) 方法创建代理对象

这个过程不复杂,容易理解,其中第 4 步会再次对 Advisor 数组进一步处理,在第 9 步根据 proxyFactory 创建代理对象

buildAdvisors 方法

buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) 方法,对 Advisor 数组进一步处理,如下:

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // Handle prototypes correctly...
    // <1> 将配置的 `interceptorNames` 转换成 Advisor 类型(默认没有)
    Advisor[] commonInterceptors = resolveInterceptorNames();

    // <2> 将 commonInterceptors 与 specificInterceptors 放入一个集合
    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
        allInterceptors.addAll(Arrays.asList(specificInterceptors));
        if (commonInterceptors.length > 0) {
            // 是否添加至最前面(默认为 true)
            if (this.applyCommonInterceptorsFirst) {
                allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
            }
            else {
                allInterceptors.addAll(Arrays.asList(commonInterceptors));
            }
        }
    }
    Advisor[] advisors = new Advisor[allInterceptors.size()];
    /*
     * <3> 遍历 `specificInterceptors` 数组
     */
    for (int i = 0; i < allInterceptors.size(); i++) {
        // <3.1> 将不是 Advisor 类型的 Advice 或者 MethodInterceptor 包装成 DefaultPointcutAdvisor 对象
        advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    // <4> 返回构建好的 Advisor 数组
    return advisors;
}

该方法的处理过程如下:

  1. 将配置的 interceptorNames 转换成 Advisor 类型(默认没有),得到 commonInterceptors 数组,如下:

    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,并包装成 Advisor 类型(如果需要的话)

  2. 将上一步获取到的 commonInterceptors 数组放入入参中的 specificInterceptors 数组中

  3. 遍历 specificInterceptors 数组

    1. 将不是 Advisor 类型的 Advice 或者 MethodInterceptor 包装成 DefaultPointcutAdvisor 对象

      // DefaultAdvisorAdapterRegistry.java
      @Override
      public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
          if (adviceObject instanceof Advisor) { // Advisor 类型,直接返回
              return (Advisor) adviceObject;
          }
          if (!(adviceObject instanceof Advice)) { // 非 Advice 接口,抛出异常
              throw new UnknownAdviceTypeException(adviceObject);
          }
          Advice advice = (Advice) adviceObject;
          if (advice instanceof MethodInterceptor) { // MethodInterceptor 类型,包装成 DefaultPointcutAdvisor 对象
              // So well-known it doesn't even need an adapter.
              return new DefaultPointcutAdvisor(advice);
          }
          for (AdvisorAdapter adapter : this.adapters) {
              // Check that it is supported.
              // 检查该 Advice 类型是否支持
              if (adapter.supportsAdvice(advice)) {
                  // 包装成 DefaultPointcutAdvisor 对象 返回
                  return new DefaultPointcutAdvisor(advice);
              }
          }
          throw new UnknownAdviceTypeException(advice);
      }
      
  4. 返回构建好的 Advisor 数组

能够应用于这个 Bean 的 Advisor 们已经准备好了,那么接下来我们来看看 ProxyFactory 是如何创建代理对象的

2. ProxyFactory

org.springframework.aop.framework.ProxyFactory,代理工厂,如下:

public Object getProxy(@Nullable ClassLoader classLoader) {
    // <1> 先创建一个 AOP 代理类(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy)
    // <2> 根据 AOP 代理为目标 Bean 创建一个代理对象,并返回
    return createAopProxy().getProxy(classLoader);
}

过程分为两步:

  1. 调用 createAopProxy() 方法,创建一个 AOP 代理类(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy),如下:

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // <1> 先获取 AOP 代理工厂,默认为 DefaultAopProxyFactory,只有这个实现
        // <2> 然后通过它根据创建当前 AdvisedSupport 配置管理器创建一个 AOP 代理(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy)
        return getAopProxyFactory().createAopProxy(this);
    }
    
  2. 然后调用 AOP 代理类的 getProxy(@Nullable ClassLoader classLoader) 方法获取代理对象

可以看到选择 JDK 动态代理还是选择 CGLIB 动态代理在 DefaultAopProxyFactory 中可以找到答案

3. DefaultAopProxyFactory

org.springframework.aop.framework.DefaultAopProxyFactory,默认的 AOP 代理工厂,如下:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		/*
		 * <1> 判断是否满足下面三个条件的其中一个
		 */
		if (config.isOptimize() // 需要优化,默认为 `false`
				|| config.isProxyTargetClass() // 使用类代理,也就是使用 CGLIB 动态代理
				|| hasNoUserSuppliedProxyInterfaces(config) // 目标类没有实现接口
		) {
			// <1.1> 获取目标类
			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.");
			}
			/*
			 * <1.2> 如果目标类是一个接口或者是 java.lang.reflect.Proxy 的子类
			 * 则还是使用 JDK 动态代理,创建一个 JdkDynamicAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
			 */
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			// <1.3> 使用 CGLIB 动态代理,创建一个  ObjenesisCglibAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
			return new ObjenesisCglibAopProxy(config);
		}
		// <2> 否则
		else {
			// 使用 JDK 动态代理,创建一个 JdkDynamicAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
			return new JdkDynamicAopProxy(config);
		}
	}

	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

创建 AOP 代理类的过程如下:

  1. 判断是否满足下面三个条件的其中一个,则进行下面的处理

    需要优化,默认为 false

    使用类代理,也就是使用 CGLIB 动态代理,在前面的 AbstractAutoProxyCreator#createProxy(..) 方法中有提到过;

    目标类没有实现接口;

    1. 获取目标类
    2. 如果目标类是一个接口或者是 java.lang.reflect.Proxy 的子类,则还是使用JDK 动态代理,创建一个 JdkDynamicAopProxy 对象
    3. 否则,使用 CGLIB 动态代理,创建一个 ObjenesisCglibAopProxy 对象
  2. 否则,使用JDK 动态代理,创建一个 JdkDynamicAopProxy 对象

我们可以看到JDK 动态代理对应 JdkDynamicAopProxy 对象,CGLIB 动态代理对应 ObjenesisCglibAopProxy(继承 CglibAopProxy)对象,在创建这两个对象的时候都传入了一个参数,就是 AdvisedSupport 配置管理器对象。

回到前面的 ProxyFactory#createAopProxy() 方法中,这个 AdvisedSupport 对象就是这个 ProxyFactory 对象,它继承了 AdvisedSupport

再回到 AbstractAutoProxyCreator#createProxy(..) 方法中,这个 ProxyFactory 对象是在这创建的,包含了 TargetSource 目标类来源和能够应用于当前目标对象的所有 Advisor

所以,我们得到的JdkDynamicAopProxy或者ObjenesisCglibAopProxy都包含了创建 AOP 代理对象的所有配置信息,可以创建代理对象了。

通过上面的这个方法,我们还可以得出一个结论,关于 proxy-target-class 配置的含义是什么?

首先这个配置表示是否进行类代理,也就是 CGLIB 动态代理,默认是 false

当为 false 时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理

如果为 true,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理

到这里,我们知道了使用哪种方式创建代理对象,那么接下里我们一起来看看两种方式创建代理对象的过程。

4. JdkDynamicAopProxy

org.springframework.aop.framework.JdkDynamicAopProxy,JDK 动态代理类,实现了 InvocationHandler 接口,可创建代理对象

构造函数

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 5531744639992436476L;

	/** We use a static Log to avoid serialization issues. */
	private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);

	/** 代理对象的配置信息,例如保存了 TargetSource 目标类来源、能够应用于目标类的所有 Advisor */
	private final AdvisedSupport advised;

	/** 目标对象是否重写了 equals 方法 */
	private boolean equalsDefined;

	/** 目标对象是否重写了 hashCode 方法 */
	private boolean hashCodeDefined;

	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 // 没有 Advisor,表示没有任何动作
				&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) // 没有来源
		{
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
	}
}

4.1 getProxy 方法

getProxy() 方法,获取一个 JDK 动态代理对象,如下:

@Override
public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); }

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    // <1> 获取需要代理的接口(目标类实现的接口,会加上 Spring 内部的几个接口,例如 SpringProxy)
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    // <2> 判断目标类是否重写了 `equals` 或者 `hashCode` 方法
    // 没有重写在拦截到这两个方法的时候,会调用当前类的实现
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // <3> 调用 JDK 的 Proxy#newProxyInstance(..) 方法创建代理对象
    // 传入的参数就是当前 ClassLoader 类加载器、需要代理的接口、InvocationHandler 实现类
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

获取代理对象的过程如下:

  1. 获取需要代理的接口(目标类实现的接口,会加上 Spring 内部的几个接口,例如 SpringProxy)

  2. 判断目标类是否重写了 equals 或者 hashCode 方法,没有重写在拦截到这两个方法的时候,会调用当前类的实现

    private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
        for (Class<?> proxiedInterface : proxiedInterfaces) {
            Method[] methods = proxiedInterface.getDeclaredMethods();
            for (Method method : methods) {
                if (AopUtils.isEqualsMethod(method)) {
                    this.equalsDefined = true;
                }
                if (AopUtils.isHashCodeMethod(method)) {
                    this.hashCodeDefined = true;
                }
                if (this.equalsDefined && this.hashCodeDefined) {
                    return;
                }
            }
        }
    }
    
  3. 调用 JDK 的 Proxy#newProxyInstance(..) 方法创建代理对象,入参的 InvocationHandler 实现了就是当前对象

对于上面 JDK 创建代理对象的过程是不是很熟悉,不清楚的小伙伴可以查看我前面 《初识 JDK、CGLIB 两种动态代理》 这篇文章

AopProxyUtils

org.springframework.aop.framework.AopProxyUtils 工具类,获取 JDK 创建代理对象时需要实现哪些接口,如下:

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
    // <1> 获取需要代理的接口(目标类实现的接口),放入 `specifiedInterfaces` 中
    Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
    if (specifiedInterfaces.length == 0) {
        // No user-specified interfaces: check whether target class is an interface.
        Class<?> targetClass = advised.getTargetClass();
        if (targetClass != null) {
            if (targetClass.isInterface()) {
                advised.setInterfaces(targetClass);
            }
            else if (Proxy.isProxyClass(targetClass)) {
                advised.setInterfaces(targetClass.getInterfaces());
            }
            specifiedInterfaces = advised.getProxiedInterfaces();
        }
    }
    // <2> 判断目标类实现的接口是否存在 SpringProxy|Advised|DecoratingProxy 接口,不存在需要添加一个
    boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
    boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
    boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
    int nonUserIfcCount = 0;
    if (addSpringProxy) {
        nonUserIfcCount++;
    }
    if (addAdvised) {
        nonUserIfcCount++;
    }
    if (addDecoratingProxy) {
        nonUserIfcCount++;
    }
    Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
    System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
    int index = specifiedInterfaces.length;
    // <3> 如果目标类实现的接口没有 SpringProxy,则添加一个
    // 这样创建的代理对象就会实现这个接口,就能知道这个代理对象是否由 Spring 创建
    if (addSpringProxy) {
        proxiedInterfaces[index] = SpringProxy.class;
        index++;
    }
    // 添加一个 Advised 接口
    if (addAdvised) {
        proxiedInterfaces[index] = Advised.class;
        index++;
    }
    // 添加一个 DecoratingProxy 接口
    if (addDecoratingProxy) {
        proxiedInterfaces[index] = DecoratingProxy.class;
    }
    // <4> 返回需要代理的接口
    return proxiedInterfaces;
}

该方法的处理过程如下:

  1. 获取需要代理的接口(目标类实现的接口),放入 specifiedInterfaces
  2. 判断目标类实现的接口是否存在 SpringProxy|Advised|DecoratingProxy 接口,不存在需要添加一个
  3. 通常情况下,上面三个接口都会添加到 specifiedInterfaces 的后面
  4. 返回 specifiedInterfaces 数组

通过上面这个方法得到的结论:在 Spring 内部通过 JDK 创建的代理对象会实现额外的接口,包括 SpringProxy 标记接口,可区分代理对象是否为 Spring 创建的

4 CglibAopProxy

org.springframework.aop.framework.CglibAopProxy,CGLIB 动态代理类,可创建代理对象

CGLIB 动态代理比 JDK 动态代理可要复杂得多~

构造函数

class CglibAopProxy implements AopProxy, Serializable {

	// Constants for CGLIB callback array indices
	// 因为 CGLIB 设置的 Callback 是一个数组,下面定义了数组中固定几个拦截器的位置
	// 进行 AOP 代理的通用拦截器
	private static final int AOP_PROXY = 0;
	// 执行目标方法的拦截器
	private static final int INVOKE_TARGET = 1;
	// 空的 Callback 对象,对于 finalize() 方法,不需要进行任何处理
	private static final int NO_OVERRIDE = 2;
	// 目标对象调度器,用于获取目标对象
	private static final int DISPATCH_TARGET = 3;
	// 配置管理器的调度器,会返回一个 AdvisedSupport 对象
	private static final int DISPATCH_ADVISED = 4;
	// 处理 `equals(Object)` 方法的拦截器
	private static final int INVOKE_EQUALS = 5;
	// 处理 `hashCode()` 方法的拦截器
	private static final int INVOKE_HASHCODE = 6;

	/** Logger available to subclasses; static to optimize serialization. */
	protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);

	/** Keeps track of the Classes that we have validated for final methods. */
	private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();

	/** 代理对象的配置信息,例如保存了 TargetSource 目标类来源、能够应用于目标类的所有 Advisor */
	protected final AdvisedSupport advised;

	/** 创建代理对象的构造方法入参 */
	@Nullable
	protected Object[] constructorArgs;

	/** 创建代理对象的构造方法的入参类型 */
	@Nullable
	protected Class<?>[] constructorArgTypes;

	/** Dispatcher used for methods on Advised. 配置管理器的调度器,会返回一个 AdvisedSupport 对象 */
	private final transient AdvisedDispatcher advisedDispatcher;

	/**
	 * 缓存方法的调用器数组索引
	 * key:方法名称
	 * value:方法对应的方法调用器在 Callback 数组中的位置
	 */
	private transient Map<String, Integer> fixedInterceptorMap = Collections.emptyMap();

	// 方法调用器在 Callback 数组中的偏移量
	private transient int fixedInterceptorOffset;

	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 // 没有 Advisor,表示没有任何动作
				&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) // 没有来源
		{
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}
}

上面的每一个属性都有注释,都非常重要,在 Spring 的 CGLIB 动态代理创建代理对象时,会设置一个 Callback 数组,上面定义了数组中固定几个拦截器的位置

数组中前面的几个 Callback 如下:

  • 0:进行 AOP 代理的通用拦截器【重点关注】
  • 1:执行目标方法的拦截器
  • 2:空的 Callback 对象,例如 finalize() 方法,不需要进行任何处理
  • 3:目标对象调度器,用于获取目标对象
  • 4:配置管理器的调度器,会返回一个 AdvisedSupport 对象
  • 5:处理 equals(Object) 方法的拦截器
  • 6:处理 hashCode() 方法的拦截器

4.1 getProxy 方法

getProxy() 方法,获取一个 CGLIB 动态代理对象,如下:

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

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    try {
        // <1> 获取目标类
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

        // <2> 将目标类作为被代理的类
        Class<?> proxySuperClass = rootClass;
        // <3> 如果目标类已经被 CGLIB 提升(名称包含 `$$` 符号)
        if (ClassUtils.isCglibProxyClass(rootClass)) {
            // <3.1> 获取目标类的父类作为被代理的类
            proxySuperClass = rootClass.getSuperclass();
            // <3.2> 获取目标类实现的接口,并添加至当前 AdvisedSupport 配置管理器中
            // 例如 `@Configuration` 注解的 Bean 会被 CGLIB 提升,实现了 EnhancedConfiguration 接口
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for (Class<?> additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }

        // Validate the class, writing log messages as necessary.
        // <4> 进行校验,仅打印日志,例如 final 修饰的方法不能被 CGLIB 提升
        validateClassIfNecessary(proxySuperClass, classLoader);

        // Configure CGLIB Enhancer...
        // <5> 创建 CGLIB 的增强类,并进行接下来的配置
        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            // `useCache` 默认为 `true`,可通过 `cglib.useCache` 系统参数指定
            if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        // <5.1> 设置被代理的类
        enhancer.setSuperclass(proxySuperClass);
        // <5.2> 设置需要代理的接口(可能没有,不过都会加上 Spring 内部的几个接口,例如 SpringProxy)
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        // <5.3> 设置命名策略,默认生成的代理对象的名称中包含 '$$' 和 'BySpringCGLIB'
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

        // <5.4> 获取回调接口,也就是 MethodInterceptor 方法拦截器
        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
        // <5.5> 设置 Callback 过滤器,用于筛选出方法对应的 Callback 回调接口
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // Generate the proxy class and create a proxy instance.
        // <6> 创建代理对象,CGLIG 字节码替身,创建目标类的子类
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {
        // 抛出 AopConfigException 异常
    }
    catch (Throwable ex) {
        // 抛出 AopConfigException 异常
    }
}

该方法的处理过程如下:

  1. 获取目标类 rootClass
  2. 将目标类作为被代理的类 proxySuperClass
  3. 如果目标类已经被 CGLIB 提升(名称包含 $$ 符号)
    1. 获取目标类的父类作为被代理的类
    2. 获取目标类实现的接口,并添加至当前 AdvisedSupport 配置管理器中,例如 @Configuration 注解的 Bean 会被 CGLIB 提升,实现了 EnhancedConfiguration 接口
  4. 进行校验,仅打印日志,例如 final 修饰的方法不能被 CGLIB 提升
  5. 创建 CGLIB 的增强类 Enhancer 对象,并进行接下来的配置
    1. 设置被代理的类为 proxySuperClass
    2. 设置需要代理的接口(例如 SpringProxy),在前面讲述 JDK 动态代理创建代理对象时已经讲过 AopProxyUtils 这个工具类,不同的是 CGLIB 不会添加 DecoratingProxy 这个接口
    3. 设置命名策略,默认生成的代理对象的名称中包含 $$BySpringCGLIB
    4. 调用 getCallbacks(Class<?>) 方法,获取回调数组 Callback[] callbacks,也就是 MethodInterceptor 方法拦截器
    5. 设置 Callback 过滤器为 ProxyCallbackFilter,用于筛选出方法使用 callbacks 中的哪个 Callback
  6. 调用 createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) 方法,创建代理对象,并返回

CGLIB 创建代理对象的过程整体上并不复杂,其中第 5.45.56 步我们接下来逐步分析

4.2 getCallbacks 方法

getCallbacks(Class<?> rootClass) 方法,获取代理对象的 Callback 回调数组,如下:

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // Parameters used for optimization choices...
    // <1> 获取代理对象的三个配置信息
    // `exposeProxy` 是否暴露代理对象,通常为 `false`
    boolean exposeProxy = this.advised.isExposeProxy();
    // `isFrozen` 配置管理器是否被冻结,通常为 `false`
    boolean isFrozen = this.advised.isFrozen();
    // `isStatic` 是否是静态的目标对象,也就是说目标对象是否每次都需要创建,通常为 `true`
    boolean isStatic = this.advised.getTargetSource().isStatic();

    // Choose an "aop" interceptor (used for AOP calls).
    // <2> 【重点】创建目标对象的拦截器,MethodInterceptor 方法拦截器,会对目标对象的方法进行拦截处理,之前筛选出来的 Advisor 会在这个里面被调用
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    // Choose a "straight to target" interceptor. (used for calls that are
    // unadvised but can return this). May be required to expose the proxy.
    // <3> 创建目标对象的执行器,用于执行目标方法
    Callback targetInterceptor;
    // <3.1> 如果需要暴露当前代理对象,则通过 AopContext 进行暴露,放入 ThreadLocal 中,其他的和下面都相同
    if (exposeProxy) {
        targetInterceptor = (isStatic ?
                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    }
    // <3.2> 否则,不暴露
    else {
        targetInterceptor = (isStatic ?
                // <3.2.1> 用于执行方法代理对象,并对最终的返回结果进一步处理(返回结果是否需要为代理对象,返回结果是否不能为空)
                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                // <3.2.2> 和上者的区别就是,每次拦截都会重新获取目标对象,结束后释放该目标对象
                new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    }

    // Choose a "direct to target" dispatcher (used for
    // unadvised calls to static targets that cannot return this).
    // <4> 目标对象调度器,用于获取目标对象
    Callback targetDispatcher = (isStatic ?
            // <4.1> 目标对象的调度器,用于获取当前目标对象
            new StaticDispatcher(this.advised.getTargetSource().getTarget()) :
            // <4.2> 目标对象的调度器,空的 Callback,不做任何处理
            new SerializableNoOp());

    // <5> 生成主要的几个回调接口,也就是上面创建的几个 Callback,放入 `mainCallbacks` 数组
    Callback[] mainCallbacks = new Callback[] {
            // 0:进行 AOP 代理的通用拦截器
            aopInterceptor,  // for normal advice
            // 1:执行目标方法的拦截器
            targetInterceptor,  // invoke target without considering advice, if optimized
            // 2:空的 Callback 对象,例如 `finalize()` 方法,不需要进行任何处理
            new SerializableNoOp(),  // no override for methods mapped to this
            // 3:目标对象调度器,用于获取目标对象
            targetDispatcher,
            // 4:配置管理器的调度器,会返回一个 AdvisedSupport 对象
            // 因为代理对象会实现 Advised 接口,拦截到其里面的方法时,需要调用当前 AdvisedSupport 的方法
            this.advisedDispatcher,
            // 5:处理 `equals(Object)` 方法的拦截器
            new EqualsInterceptor(this.advised),
            // 6:处理 `hashCode()` 方法的拦截器
            new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

    // If the target is a static one and the advice chain is frozen,
    // then we can make some optimizations by sending the AOP calls
    // direct to the target using the fixed chain for that method.
    /*
     * <6> 如果目标对象不需要每次都创建,且当前 AdvisedSupport 配置管理器被冻结了,性能优化,可暂时忽略
     * 那么在创建代理对象的时候,就可以先将目标对象的每个方法对应的方法调用器解析出来,该过程有点性能损耗,这样在代理对象执行方法的时候性能有所提升
     * 不过由于这里会解析出许多方法调用器,会占有一定的内存,以空间换时间
     */
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<>(methods.length);

        // TODO: small memory optimization here (can skip creation for methods with no advice)
        /*
         * <6.1> 遍历目标对象所有的方法
         */
        for (int x = 0; x < methods.length; x++) {
            Method method = methods[x];
            // <6.1.1> 获取能够应用于该方法的所有拦截器(有序)
            // 不同的 AspectJ 根据 @Order 排序
            // 同一个 AspectJ 中的 Advice 排序:AspectJAfterThrowingAdvice > AfterReturningAdviceInterceptor > AspectJAfterAdvice > AspectJAroundAdvice > MethodBeforeAdviceInterceptor
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
            // <6.1.2> 创建一个方法调用器
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            // <6.1.3> 将每个方法的对应的调用器的位置索引缓存起来
            this.fixedInterceptorMap.put(methods.toString(), x);
        }

        // Now copy both the callbacks from mainCallbacks
        // and fixedCallbacks into the callbacks array.
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        // <6.2> 将 `mainCallbacks` 复制到 `callbacks` 数组
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        // <6.3> 将 `fixedCallbacks` 复制到 `callbacks` 数组(拼接在后面)
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        // <6.4> 记录一个已生成的方法调用器的偏移量
        this.fixedInterceptorOffset = mainCallbacks.length;
    }
    // <7> 否则,不进行解析,取上面的几个主要的 Callback
    else {
        callbacks = mainCallbacks;
    }
    // <8> 返回这个目标对象对应的 Callback 数组
    return callbacks;
}

该方法的处理过程如下:

  1. 是获取代理对象的三个配置信息

    • exposeProxy 是否暴露代理对象,通常为 false
    • isFrozen 配置管理器是否被冻结,通常为 false
    • isStatic 是否是静态的目标对象,也就是说目标对象是否每次都需要创建,通常为 true
  2. 【重点】创建目标对象的拦截器,DynamicAdvisedInterceptor 方法拦截器,会对目标对象的方法进行拦截处理,代理对象的处理逻辑都在这里面完成

  3. 创建目标对象的执行器,用于执行目标方法

    1. 如果需要暴露当前代理对象,则通过 AopContext 进行暴露,放入 ThreadLocal 中,其他的和下面都相同
    2. 否则,不暴露
      1. isStatic 为 true,创建 StaticUnadvisedInterceptor 对象,用于执行方法代理对象,并对最终的返回结果进一步处理(返回结果是否需要为代理对象,返回结果是否不能为空)
      2. 否则,创建 DynamicUnadvisedInterceptor 对象,和上者的区别就是,每次拦截都会重新获取目标对象,结束后释放该目标对象
  4. 目标对象调度器,用于获取目标对象

    1. isStatic 为 true,创建 StaticDispatcher 对象,目标对象的调度器,用于获取当前目标对象
    2. 否则,创建 SerializableNoOp 对象,空的 Callback,不做任何处理
  5. 生成主要的几个回调接口,也就是上面创建的几个 Callback,放入 mainCallbacks 数组,可以回到上面的构造函数看看哦😈

    0:进行 AOP 代理的通用拦截器

    1:执行目标方法的拦截器

    2:空的 Callback 对象,例如 finalize() 方法,不需要进行任何处理

    3:目标对象调度器,用于获取目标对象

    4:配置管理器的调度器,会返回一个 AdvisedSupport 对象,因为代理对象会实现 Advised 接口,拦截到其里面的方法时,需要调用当前 AdvisedSupport 的方法

    5:处理 equals(Object) 方法的拦截器

    6:处理 hashCode() 方法的拦截器

  6. 如果目标对象不需要每次都创建,且当前 AdvisedSupport 配置管理器被冻结了(默认不会),这一步做了一个性能优化,具体查看上面的代码

    在创建代理对象的时候,就可以先将目标对象的每个方法对应的方法调用器解析出来,该过程有点性能损耗,这样在代理对象执行方法的时候性能有所提升;不过由于这里会解析出许多方法调用器,会占有一定的内存,以空间换时间

  7. 否则,不进行解析,取上面 mainCallbacks

  8. 返回这个目标对象对应的 Callback 数组

获取代理对象的 Callback 过程稍微有点复杂,因为代理对象处理不同的方法使用到的 Callback 也是不同的。不过你要知道的是上面第 2 步,第一个 Callback 就是 DynamicAdvisedInterceptor 对象,该对象用于进行 AOP 代理的通用拦截器,目标类的方法在这个拦截器中进行处理。这个对象和 JDK 动态代理创建的代理对象的实现差不多,所以都放入下一篇文章进行分析😈

4.3 ProxyCallbackFilter

CglibAopProxy 的私有内部静态类,用于筛选方法出对应的 Callback 对象

private static class ProxyCallbackFilter implements CallbackFilter {

    private final AdvisedSupport advised;

    private final Map<String, Integer> fixedInterceptorMap;

    private final int fixedInterceptorOffset;

    public ProxyCallbackFilter(
            AdvisedSupport advised, Map<String, Integer> fixedInterceptorMap, int fixedInterceptorOffset) {
        this.advised = advised;
        this.fixedInterceptorMap = fixedInterceptorMap;
        this.fixedInterceptorOffset = fixedInterceptorOffset;
    }

    /**
     * 根据 Method 返回我们需要的 Callback 在数组中的位置
     */
    @Override
    public int accept(Method method) {
        // <1> 如果该方法是 `finalize()`
        if (AopUtils.isFinalizeMethod(method)) {
            // 返回一个空 Callback 对象,不对该方法做任何处理
            return NO_OVERRIDE;
        }
        // <2> 如果该方法是 Advised 中的方法,也就是需要 AdvisedSupport 来执行
        if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // 返回一个配置管理器的调度器,会返回一个 AdvisedSupport 对象去执行这个方法
            return DISPATCH_ADVISED;
        }
        // We must always proxy equals, to direct calls to this.
        // <3> 如果该方法是 `equals(Object)` 方法
        if (AopUtils.isEqualsMethod(method)) {
            // 返回处理 `equals(Object)` 方法的拦截器去执行该方法
            return INVOKE_EQUALS;
        }
        // We must always calculate hashCode based on the proxy.
        // <4> 如果该方法是 `hashCode()` 方法
        if (AopUtils.isHashCodeMethod(method)) {
            // 返回处理 `hashCode()` 方法的拦截器去执行该方法
            return INVOKE_HASHCODE;
        }
        // <5> 获取目标类 Class 对象
        Class<?> targetClass = this.advised.getTargetClass();
        // Proxy is not yet available, but that shouldn't matter.
        // <6> 获取能够应用于该方法的所有拦截器,仅判断是否存在 Advice
        List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        boolean haveAdvice = !chain.isEmpty();
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isStatic = this.advised.getTargetSource().isStatic();
        boolean isFrozen = this.advised.isFrozen();
        // <7> 如果有 Advice 或者配置没有被冻结,通常情况都会进入这里
        if (haveAdvice || !isFrozen) {
            // If exposing the proxy, then AOP_PROXY must be used.
            // <7.1> 如果需要暴露这个代理对象,默认为 `false`
            if (exposeProxy) {
                // 返回处理 AOP 代理的通用拦截器去执行该方法
                return AOP_PROXY;
            }
            String key = method.toString();
            // Check to see if we have fixed interceptor to serve this method.
            // Else use the AOP_PROXY.
            // <7.2> 如果目标对象是单例的,且配置被冻结,且存在对应的方法调用器
            if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
                // We know that we are optimizing so we can use the FixedStaticChainInterceptors.
                // 返回已经存在的方法调用器
                int index = this.fixedInterceptorMap.get(key);
                return (index + this.fixedInterceptorOffset);
            }
            // <7.3> 否则(通常会走到这一步)
            else {
                // 返回处理 AOP 代理的通用拦截器去执行该方法
                return AOP_PROXY;
            }
        }
        // <8> 否则
        else {
            // <8.1> 如果需要暴露代理对象,或者不是单例模式,默认这两种情况都不满足
            if (exposeProxy || !isStatic) {
                // 则返回执行目标方法的拦截器
                return INVOKE_TARGET;
            }
            Class<?> returnType = method.getReturnType();
            // <8.2> 如果该方法需要返回的就是目标类,暂时不清楚这种情况
            if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
                // 那么返回执行目标方法的拦截器,返回当前对象
                return INVOKE_TARGET;
            }
            // <8.3> 否则,返回目标对象调度器,用于获取目标对象,让目标对象自己去执行这个方法
            else {
                return DISPATCH_TARGET;
            }
        }
    }
}

我们直接看到实现的 accept(Method method) 方法的处理逻辑:

  1. 如果该方法是 finalize(),返回一个空 Callback 对象,不对该方法做任何处理
  2. 如果该方法是 Advised 中的方法,也就是需要 AdvisedSupport 来执行,返回一个配置管理器的调度器,会返回一个 AdvisedSupport 对象去执行这个方法
  3. 如果该方法是 equals(Object) 方法,返回处理 equals(Object) 方法的拦截器去执行该方法
  4. 如果该方法是 hashCode() 方法,返回处理 hashCode() 方法的拦截器去执行该方法
  5. 获取目标类 Class 对象
  6. 获取能够应用于该方法的所有拦截器,仅判断是否存在 Advice
  7. 如果有 Advice 或者配置没有被冻结,通常情况都会进入这里
    1. 如果需要暴露这个代理对象,默认为 false,返回处理 AOP 代理的通用拦截器去执行该方法
    2. 如果目标对象是单例的,且配置被冻结,且存在对应的方法调用器,返回已经存在的方法调用器
    3. 否则(通常会走到这一步),返回进行 AOP 代理的通用拦截器去执行该方法
  8. 否则
    1. 如果需要暴露代理对象,或者不是单例模式,默认这两种情况都不满足,返回执行目标方法的拦截器
    2. 如果该方法需要返回的就是目标类,暂时不清楚这种情况,那么返回执行目标方法的拦截器,返回当前对象
    3. 否则,返回目标对象调度器,用于获取目标对象,让目标对象自己去执行这个方法

上面的处理过程基本上都根据 Method 进行判断,然后返回一个 int 数值,这个值代表去取 Callback 数组中的那个 Callback,回看上面讲到的几个方法你就全部理解了。

我们来看到上面的第 7.3 步,返回的是一个 0,表示使用第一个 Callback 进行处理,对应的就是 DynamicAdvisedInterceptor 对象,这个对象和 JDK 动态代理创建的代理对象的实现差不多,所以都放入下一篇文章进行分析😈

4.4 createProxyClassAndInstance 方法

createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) 方法,创建代理对象,如下:

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    // 设置使用构造器期间不进行拦截
    enhancer.setInterceptDuringConstruction(false);
    // 设置 Callback 数组
    enhancer.setCallbacks(callbacks);
    // 创建一个代理对象(目标类的子类)
    return (this.constructorArgs != null && this.constructorArgTypes != null ?
            // 使用指定的构造方法
            enhancer.create(this.constructorArgTypes, this.constructorArgs) :
            // 使用默认的构造方法
            enhancer.create());
}

这个方法在 ObjenesisCglibAopProxy 子类中被重写了,Spring 内部也是使用 ObjenesisCglibAopProxy 这个类,因为 CGLIB 创建的子类考虑到通过构造器实例化代理对象,可能会存在构造器不合适的情况,所以 Spring 采用 Objenesis 实例化对象,不通过构造器创建实例对象

4.4 ObjenesisCglibAopProxy

org.springframework.aop.framework.ObjenesisCglibAopProxy,继承 CglibAopProxy 类,重写 createProxyClassAndInstance(..) 方法

class ObjenesisCglibAopProxy extends CglibAopProxy {

	/**
	 * 创建一个 Objenesis 对象
	 * [**Objenesis**](http://objenesis.org/) 是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象
	 * 应用场景:
	 * 1. 序列化,远程调用和持久化 - 对象需要实例化并存储为到一个特殊的状态,而没有调用代码
	 * 2. 代理,AOP 库和 Mock 对象 - 类可以被子类继承而子类不用担心父类的构造器
	 * 3. 容器框架 - 对象可以以非标准的方式被动态实例化
	 */
	private static final SpringObjenesis objenesis = new SpringObjenesis();

	public ObjenesisCglibAopProxy(AdvisedSupport config) {
		super(config);
	}

	@Override
	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		// <1> 先创建代理对象的 Class 对象(目标类的子类)
		Class<?> proxyClass = enhancer.createClass();
		Object proxyInstance = null;

		// <2> 是否使用 Objenesis 来实例化代理对象,默认会
		// 可通过 在 `spring.properties` 文件中添加 `spring.objenesis.ignore=false` 来禁止
		if (objenesis.isWorthTrying()) {
			try {
				// <2.1> 通过 Objenesis 实例化代理对象(非标准方式,不使用构造方法进行实例化)
				proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
			}
			catch (Throwable ex) {
				logger.debug("Unable to instantiate proxy using Objenesis, " +
						"falling back to regular proxy construction", ex);
			}
		}

		// <3> 如果借助 Objenesis 实例化代理对象失败
		if (proxyInstance == null) {
			// Regular instantiation via default constructor...
			try {
				// <3.1> 选择构造器,指定了参数则使用对应的构造器,否则使用默认构造器
				Constructor<?> ctor = (this.constructorArgs != null ?
						proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
						proxyClass.getDeclaredConstructor());
				ReflectionUtils.makeAccessible(ctor);
				// <3.2> 通过构造器实例化代理对象(反射)
				proxyInstance = (this.constructorArgs != null ?
						ctor.newInstance(this.constructorArgs) : ctor.newInstance());
			}
			catch (Throwable ex) {
				throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
						"and regular proxy instantiation via default constructor fails as well", ex);
			}
		}

		// <4> 设置 Callback 数组
		((Factory) proxyInstance).setCallbacks(callbacks);
		// <5> 返回代理对象
		return proxyInstance;
	}
}

首先我们来看到 SpringObjenesis 这个对象,它实现了 Objenesis 接口,Objenesis 是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象,应用场景:

  • 序列化,远程调用和持久化 - 对象需要实例化并存储为到一个特殊的状态,而没有调用代码
  • 代理,AOP 库和 Mock 对象 - 类可以被子类继承而子类不用担心父类的构造器
  • 容器框架 - 对象可以以非标准的方式被动态实例化

创建代理对象的过程如下:

  1. 先通过 Enhancer 创建代理对象的 Class 对象(目标类的子类)
  2. 是否使用 Objenesis 来实例化代理对象,默认会
    1. 通过 Objenesis 实例化代理对象(非标准方式,不使用构造方法进行实例化)
  3. 如果借助 Objenesis 实例化代理对象失败
    1. 选择构造器,指定了参数则使用对应的构造器,否则使用默认构造器
    2. 通过构造器实例化代理对象(反射)
  4. 设置 Callback 数组
  5. 返回代理对象

总结

在前面的《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:

  1. 筛选出能够应用于当前 Bean 的 Advisor
  2. 找到了合适 Advisor 则创建一个代理对象, JDK 动态代理或者 CGLIB 动态代理

上一篇《Spring AOP 自动代理(二)筛选合适的通知器》文章分析了上面第 1 步的处理过程。本文是接着前面两篇文章分析上面第 2 个过程,Spring 是如何创建代理对象的,大致流程如下:

  1. 创建一个 ProxyFactory 代理工厂对象,设置需要创建的代理类的配置信息,例如 Advisor 数组和 TargetSource 目标类来源

  2. 借助 DefaultAopProxyFactory 选择 JdkDynamicAopProxy(JDK 动态代理)还是 ObjenesisCglibAopProxy(CGLIB 动态代理)

    • proxy-target-classfalse 时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理

    • 如果为 true,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理

  3. 通过 JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy 创建一个代理对象

    • JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的 Proxy.newProxyInstance(..) 创建代理对象
    • ObjenesisCglibAopProxy 借助 CGLIB 的 Enhancer 创建代理对象,会设置 Callback 数组和 CallbackFilter 筛选器(选择合适 Callback 处理对应的方法),整个过程相比于 JDK 动态代理更复杂点,主要的实现在 DynamicAdvisedInterceptor 方法拦截器中

其中 CGLIB 实例化代理对象的过程使用到了 Objenesis,它是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象。因为 CGLIB 创建的子类考虑到通过构造器实例化代理对象,可能会存在构造器不合适的情况,所以 Spring 采用 Objenesis 实例化对象,不通过构造器创建实例对象。

好了,本篇文章就到这里了,Spring AOP 中整个自动代理过程到这里也就结束了。对于 JDK 动态代理和 CGLIB 动态代理创建的代理对象,它们的具体实现(或者说是方法拦截处理)在这里并没有体现出来,前者的实现在 JdkDynamicAopProxy 中,因为它实现了 InvocationHandler 接口,后者的实现则在 DynamicAdvisedInterceptor 方法拦截器中,这些内容将在下篇文章进行分析。

posted @ 2021-04-21 18:05  月圆吖  阅读(2295)  评论(5编辑  收藏  举报