Spring AOP源码分析(二)——创建代理对象

AbstractAutoProxyCreator/ProxyFactory/JdkDynamicAopProxy/CglibAopProxy

Posted by Jay on July 27, 2019

Spring AOP源码分析(二)——创建代理对象

上一篇文章Spring AOP源码分析(一)——筛选合适的通知器,分析了Spring是如何为目标bean筛选合适的通知器的。现在通知器选好了,接下来就要通过动态代理的方式将通知器(Advisor)所持有的通知(Advice)织入到bean的某些方法前后(即创建代理对象)。与筛选合适的通知器相比,创建代理对象的过程则要简单不少。下面先来了解一下相关的背景知识,再来分析创建代理对象的过程。

一、背景知识

1. proxy-target-class

在Spring AOP配置中,proxy-target-class属性可影响Spring生成的代理对象的类型(代理由CGLib生成或JDK Proxy生成)。以XML配置为例,可进行如下配置:

<aop:aspectj-autoproxy proxy-target-class="true"/>

<aop:config proxy-target-class="true">
    <aop:aspect id="xxx" ref="xxxx">
        <!-- 省略 -->
    </aop:aspect>
</aop:config>

如上,默认情况下proxy-target-class属性为false。当目标bean实现了接口时,Spring会基于JDK动态代理为目标 bean创建代理对象。若未实现任何接口,Spring则会通过CGLib创建代理。而当proxy-target-class属性设为true时,则会强制Spring通过CGLib的方式创建代理对象,即使目标bean实现了接口。

关于proxy-target-class属性的用途介绍完毕,下面来看看两种不同创建动态代理的方式。

2. 动态代理
(1) 基于JDK的动态代理

基于JDK的动态代理主要是通过JDK提供的代理创建类Proxy为目标对象创建代理,下面来看一下Proxy中创建代理的方法声明。如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 	
                                      InvocationHandler h)

介绍一下上面的参数列表:

  • loader——类加载器;
  • interfaces——目标类所实现的接口列表;
  • h——用于封装代理的处理逻辑。

JDK动态代理对目标类是有一定要求的,即要求目标类必须实现了接口,JDK动态代理只能为实现了接口的目标类生成代理对象。至于InvocationHandler,是一个接口类型,定义了一个invoke方法。使用者需要实现该方法,并在其中封装代理逻辑。

关于JDK动态代理的介绍,就先说到这。下面来演示一下JDK 动态代理的使用方式,如下:

public interface UserService {

    void save(User user);

    void update(User user);
}

public class UserServiceImpl implements UserService {

    @Override
    public void save(User user) {
        System.out.println("save user info");
    }

    @Override
    public void update(User user) {
        System.out.println("update user info");
    }
}

代理创建者定义:

public interface ProxyCreator {

    Object getProxy();
}

public class JdkProxyCreator implements ProxyCreator, InvocationHandler {

    private Object target;

    public JdkProxyCreator(Object target) {
        assert target != null;
        Class<?>[] interfaces = target.getClass().getInterfaces();
        if (interfaces.length == 0) {
            throw new IllegalArgumentException("target class don`t implement any interface");
        }
        this.target = target;
    }

    @Override
    public Object getProxy() {
        Class<?> clazz = target.getClass();
        // 生成代理对象
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println(System.currentTimeMillis() + " - " + method.getName() + " method start");
        // 调用目标方法
        Object retVal = method.invoke(target, args);
        System.out.println(System.currentTimeMillis() + " - " + method.getName() + " method over");

        return retVal;
    }
}

如上,invoke方法中的代理逻辑主要用于记录目标方法的调用时间和结束时间。下面写测试代码简单验证一下:

public class JdkProxyCreatorTest {

    @Test
    public void getProxy() throws Exception {
        ProxyCreator proxyCreator = new JdkProxyCreator(new UserServiceImpl());
        UserService userService = (UserService) proxyCreator.getProxy();
        
        System.out.println("proxy type = " + userService.getClass());
        System.out.println();
        userService.save(null);
        System.out.println();
        userService.update(null);
    }
}

测试结果如下:

从测试结果中可以看出,代理逻辑得到正常执行。另外,注意一下userService指向对象的类型,并非是 xyz.coolblog.proxy.UserServiceImpl,而是com.sun.proxy.$Proxy4(Proxy子类)

(2) 基于CGLib的动态代理

当要为未实现接口的类生成代理时,就无法使用JDK动态代理。那么此类的目标对象生成代理时就需要使用CGLib。在CGLib中,代理逻辑是封装在MethodInterceptor实现类中的,代理对象则是通过Enhancer类的create方法进行创建。下面演示一下CGLib创建代理对象的过程:

被代理类:

public class Tank59 {
    void run() {
        System.out.println("极速前行中....");
    }

    void shoot() {
        System.out.println("轰...轰...轰...轰...");
    }
}

CGLib代理创建者:

public class CglibProxyCreator implements ProxyCreator {

    private Object target;

    private MethodInterceptor methodInterceptor; // 拦截器

    public CglibProxyCreator(Object target, MethodInterceptor methodInterceptor) {
        assert (target != null && methodInterceptor != null);
        this.target = target;
        this.methodInterceptor = methodInterceptor;
    }

    @Override
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        // 设置代理类的父类
        enhancer.setSuperclass(target.getClass());
        // 设置代理逻辑
        enhancer.setCallback(methodInterceptor);
        // 创建代理对象
        return enhancer.create();
    }
}

方法拦截器MethodInterceptor:

public class TankRemanufacture implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if (method.getName().equals("run")) {
            System.out.println("正在重造59坦克...");
            System.out.println("重造成功,已获取 59改 之 超音速飞行版");
            System.out.print("已起飞,正在突破音障。");

            methodProxy.invokeSuper(o, objects);

            System.out.println("已击落黑鸟 SR-71,正在返航...");
            return null;
        }

        return methodProxy.invokeSuper(o, objects);
    }
}

测试代码如下:

public class CglibProxyCreatorTest {

    @Test
    public void getProxy() throws Exception {
        ProxyCreator proxyCreator = new CglibProxyCreator(new Tank59(), new TankRemanufacture());
        Tank59 tank59 = (Tank59) proxyCreator.getProxy();
        
        System.out.println("proxy class = " + tank59.getClass() + "\n");
        tank59.run();
        System.out.println();
        System.out.print("射击测试:");
        tank59.shoot();
    }
}

测试结果如下:

如上,“极速前行中…” 和 “轰…轰…轰…轰…” 这两行字符串是目标对象中的方法打印出来的,其他的则是由代理逻辑打印的。由此可知,代理逻辑已生效。

二、代理对象创建过程分析

Spring AOP在为目标bean创建代理对象前,需要先创建AopProxy对象,然后再调用该对象的getProxy方法创建实际的代理类。先来看看AopProxy这个接口的定义,如下:

public interface AopProxy {

    /** 创建代理对象 */
    Object getProxy();
    
    Object getProxy(ClassLoader classLoader);
}

在Spring中,有两个类实现AopProxy,如下:

Spring AOP在为目标bean创建代理的过程中,要根据bean是否实现接口,以及一些其他配置来决定使用AopProxy何种实现类为目标bean创建代理对象。下面来看一下代理创建的过程,如下:

// AbstractAutoProxyCreator类,创建代理对象
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); // 复制ProxyConfig配置
   // 判断是否代理 类 或者 接口
   // 默认配置下,或用户显式配置 proxy-target-class = "false" 时,
   // 这里的 proxyFactory.isProxyTargetClass() 也为 false
   if (!proxyFactory.isProxyTargetClass()) { // 如果配置的proxyTargetClass为false,进入下面的判断
      // 检查BeanDefinition preserveTargetClass属性,来判断是否代理类
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         // 检查接口来判断是否代理接口或者类
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
   // 构建最终的Advisor数组
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors); // 添加advisor
   proxyFactory.setTargetSource(targetSource); // 设置TargetSource
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
   // 创建代理
   return proxyFactory.getProxy(getProxyClassLoader());
}

public Object getProxy(@Nullable ClassLoader classLoader) {
	// 先创建 AopProxy 实现类对象(如JdkDynamicAopProxy),然后再调用 getProxy 为目标 bean 创建代理对象
	return createAopProxy().getProxy(classLoader);
}
(1) 配置proxyTargetClass属性

在创建代理对象时,会先判断是否代理接口或者代理类。

if (!proxyFactory.isProxyTargetClass()) { // 如果配置的proxyTargetClass为false,进入下面的判断
  // 检查BeanDefinition preserveTargetClass属性,来判断是否代理类
  if (shouldProxyTargetClass(beanClass, beanName)) {
     proxyFactory.setProxyTargetClass(true);
  }
  else {
     // 检查接口来判断是否代理接口或者类
     evaluateProxyInterfaces(beanClass, proxyFactory);
  }
}

shouldProxyTargetClass方法检查BeanDefinition的preserveTargetClass属性,来判断是否代理类:

protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
   return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
         // 检查preserveTargetClass属性
         AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
// AutoProxyUtils类
public static boolean shouldProxyTargetClass(
		ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

	if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
		BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
    // 检查preserveTargetClass属性是否为true
		return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
	}
	return false;
}

而evaluateProxyInterfaces方法检查接口来判断是否代理接口或者类:

// 评估代理接口
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
   // 获取beanClass及其父类实现的所有接口
   Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
   boolean hasReasonableProxyInterface = false;
   for (Class<?> ifc : targetInterfaces) {
      // 判断是否存在合理的代理接口(去除容器回调接口、内部语言接口)
      if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
            ifc.getMethods().length > 0) {
         hasReasonableProxyInterface = true;
         break;
      }
   }
   if (hasReasonableProxyInterface) {
      // Must allow for introductions; can't just set interfaces to the target's interfaces only.
      for (Class<?> ifc : targetInterfaces) {
         proxyFactory.addInterface(ifc); // 如果存在合理的代理接口,则添加代理接口
      }
   }
   else {
      proxyFactory.setProxyTargetClass(true); // 代理类
   }
}
(2) 构建最终的Advisor数组

构建最终的Advisor数组,将MethodInterceptor、Advice适配为Advisor。

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
   // Handle prototypes correctly...
   Advisor[] commonInterceptors = resolveInterceptorNames(); // 解析通过setInterceptorNames设置的拦截器

   List<Object> allInterceptors = new ArrayList<>();
   if (specificInterceptors != null) {
      allInterceptors.addAll(Arrays.asList(specificInterceptors));
      if (commonInterceptors.length > 0) {
         // 先应用commonInterceptors中的拦截器 与否
         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++) {
      // 如果有必要,将MethodInterceptor、Advice,包装为Advisor
      advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
   }
   return advisors;
}
// 解析通过setInterceptorNames设置的拦截器
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);
			// 对于interceptorNames中的拦截器(MethodInterceptor、Advice),包装为Advisor
			advisors.add(this.advisorAdapterRegistry.wrap(next));
		}
	}
	return advisors.toArray(new Advisor[0]);
}
(3) 创建代理对象

getProxy有两个方法调用,一个是调用createAopProxy创建AopProxy实现类对象,然后再调用AopProxy实现类对象中的getProxy方法创建代理对象。这里先来看一下创建AopProxy实现类对象的过程,如下:

protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate(); // 设置标记
   }
   return getAopProxyFactory().createAopProxy(this);
}

// 返回DefaultAopProxyFactory实例
public AopProxyFactory getAopProxyFactory() {
	return this.aopProxyFactory;
}

// DefaultAopProxyFactory类
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// 下面的三个条件简单分析一下:
	//   条件1:config.isOptimize() - 是否需要优化
	//   条件2:config.isProxyTargetClass() - 检测proxyTargetClass的值,前面的代码会设置这个值
	//   条件3:hasNoUserSuppliedProxyInterfaces(config) - 是否不存在用户定义的代理接口
	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.");
		}
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			// 创建JDK动态代理
			return new JdkDynamicAopProxy(config);
		}
		// 创建CGLib代理,ObjenesisCglibAopProxy继承自CglibAopProxy
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		// 创建JDK动态代理
		return new JdkDynamicAopProxy(config);
	}
}

如上,DefaultAopProxyFactory根据一些条件决定生成什么类型的AopProxy实现类对象。生成好AopProxy实现类对象后,下面就要为目标bean创建代理对象了。这里以JdkDynamicAopProxy为例,来看一下该类的getProxy方法的执行逻辑。

public Object getProxy() {
	return getProxy(ClassUtils.getDefaultClassLoader());
}
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);
   // 确定所有代理接口中是否定义了equals和hashCode方法
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   // 调用 newProxyInstance 创建代理对象
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

确定完整的代理接口:

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
   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(); // 获取更新后的代理接口数组
      }
   }
  // 判断是否添加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;
   // 添加SpringProxy、Advised、DecoratingProxy接口
   if (addSpringProxy) {
      proxiedInterfaces[index] = SpringProxy.class;
      index++;
   }
   if (addAdvised) {
      proxiedInterfaces[index] = Advised.class;
      index++;
   }
   if (addDecoratingProxy) {
      proxiedInterfaces[index] = DecoratingProxy.class;
   }
   return proxiedInterfaces;
}

确定所有代理接口中是否定义了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;
         }
      }
   }
}

根据如上JdkDynamicAopProxy创建代理的代码,JdkDynamicAopProxy最终调用Proxy.newProxyInstance方法来创建代理对象

至此,创建代理对象的整个过程分析完毕。

参考文章