Spring源码解析AOP(三)AOP代理的生成

本文解析了Spring AOP如何根据配置选择JDK或CGLIB动态代理生成代理对象的过程。详细介绍了createProxy()方法中代理工厂的配置及代理对象的创建细节。

前言

上一篇【Spring源码解析AOP(二)AOP后置处理器的工作】说到处理AOP的后置处理器即将创建真实Bean的代理对象,用于使用AOP功能,本篇就接着上次说到的createProxy()方法继续,看看Spring是怎么为一个原生对象创建一个代理的。更多Spring内容进入【Spring解读系列目录】

为创建代理做准备

接着上篇进入createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean))方法,注意这个时候已经把bean的类信息,类名,过滤器,以及bean对象传递进去了。

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);

   if (!proxyFactory.isProxyTargetClass()) {
      //判断是不是需要CGLIB代理
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true); //需要就设置为true
      }
      else { //否则就使用JDK动态代理
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
   //把切面信息放到这里来
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   //初始化proxyFactory的各种信息,before,after,around,具体内容之类的。为了创建代理使用的
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
   //得到代理,那么代理对象就是在这里被创建的
   return proxyFactory.getProxy(getProxyClassLoader());
}

在这个方法里进行了一系列的设置,传递方法,是不是使用CGLIB动态代理,切面信息等等内容给代理工厂,最终在最后面的proxyFactory.getProxy(getProxyClassLoader());把代理创建出来。

选择动态代理的方式

public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}

这里createAopProxy()是在AopProxy接口中的方法,它有三个实现:CglibAopProxyJdkDynamicAopProxy、和ObjenesisCglibAopProxy具体是哪个实现要看这个方法里面的选择。

protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate();
   }
  return getAopProxyFactory().createAopProxy(this);
}

继续进入createAopProxy()方法,看怎么选择实现类。这个方法的实现是在DefaultAopProxyFactory#createAopProxy()这里。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   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.");
      }
      //如果目标对象是一个接口,或者是一个代理,Spring仍然会使用JDK动态代理
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {//如果什么都不开启,使用JDK动态代理,那么上一层调用的就是JdkDynamicAopProxy里面的getProxy(),直接去里面看
      return new JdkDynamicAopProxy(config);
   }
}

首先进入到第一个if语句里: config.isOptimize()条件这个值在xml里面可以配置,意思为 是否对生产代理策略使用优化,默认为false;config.isProxyTargetClass()条件在@EnableAspectJAutoProxy(proxyTargetClass = true)这里设置,意思是是否开启CGLIB代理,默认为false;hasNoUserSuppliedProxyInterfaces(config) 条件,意为是否存在代理接口,默认为fasle;如果直接开启Spring,而不做任何操作,整个if条件为false,直接到else使用JDK动态代理。最终会看到其实最后如果不是JDK动态代理,就是CGLIB动态代理生了AOP的代理对象。而之所以说Spring默认的就是JDK动态代理,也是因为这里。如果Spring一切配置都是默认的话,就会走到JdkDynamicAopProxy这个类去生成AOP代理。

JDK动态代理生成AOP

如果由JDK最终生成,那么最终将会由JdkDynamicAopProxy#getProxy(ClassLoader)方法去实现这个代理。看到下面最后return的代码,笔者相信任何对代理熟悉的同学都知道,这里生成了代理共给AOP使用。

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);
   //看这里Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);,做了一个代理对象。
   //所以说Spring底层用的是动态代理
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

CGLIB动态代理生成AOP

说完JDK,开启了CGLIB后这里又是怎么做的呢?进入CglibAopProxy#getProxy(ClassLoader)

public Object getProxy(@Nullable ClassLoader classLoader) {
      /**略去代理对象的配置**/
      //关键在这里
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (Throwable ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

方法很长,简化一下。最终落脚点就在createProxyClassAndInstance(enhancer, callbacks);这个方法里。首先尝试从缓存中拿,如果拿不到,就使用构造方法的newInstance()反射生成一个代理返回出去。

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
   Class<?> proxyClass = enhancer.createClass();
   Object proxyInstance = null;
   if (objenesis.isWorthTrying()) {
      try { //企图从cache中拿
         proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
      }
      catch (Throwable ex) {
         logger.debug("Unable to instantiate proxy using Objenesis, " +
               "falling back to regular proxy construction", ex);
      }
   }
   if (proxyInstance == null) {
      // Regular instantiation via default constructor...
      try { //如果拿不到使用构造方法反射生成代理
         Constructor<?> ctor = (this.constructorArgs != null ?
               proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
               proxyClass.getDeclaredConstructor());
         ReflectionUtils.makeAccessible(ctor);
         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);
      }
   }
   ((Factory) proxyInstance).setCallbacks(callbacks);
   return proxyInstance;
}

总结

到此SpringAOP代理的生成就结束了,中间还有忽略了Bean的生成过程,这一过程太过于复杂,等笔者捋顺了在写帖子发出来吧。那么最后总结一下这三篇的内容:首先开启AOP,引入执行AOP动态代理的后置处理器,然后Spring容器负责把bean创建出来(new出来),由AOPBeanPostProcessor负责收集Bean实例、切面等等信息传给代理选择器,最后根据配置选除合适的代理处理类,把AOP动态代理创建出来,到此SpringAOP动态代理完成,撒花。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值