【JavaEE进阶】 Spring AOP源码简单剖析
作者:mmseoamin日期:2024-04-27

文章目录

  • 🍃前言
  • 🍀Spring AOP源码剖析
  • ⭕总结

    🍃前言

    前面的博客中,博主对代理模式进行了一个简单的讲解,接下来博主将对Spring AOP源码进行简单剖析,使我们对Spring AOP了解的更加深刻。

    🍀Spring AOP源码剖析

    Spring AOP 主要基于两种⽅式实现的:JDK 及 CGLIB 的⽅式

    Spring对于AOP的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成⽣成代理对象的逻辑在⽗类 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);
    /**
     * 检查proxyTargetClass属性值,spring默认为false
     * proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理
     * 如果代理对象为类, 设置为true, 使⽤cglib代理
     */
        if (!proxyFactory.isProxyTargetClass()) {
    //是否有设置cglib代理
            if (shouldProxyTargetClass(beanClass, beanName)) {
    //设置proxyTargetClass为true,使⽤cglib代理
                proxyFactory.setProxyTargetClass(true);
            } else {
    /**
     * 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理
     * 否则CGLIB代理(设置ProxyTargetClass为true )
     * 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其
     设为true
     */
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
    // Use original ClassLoader if bean class not locally loaded in overriding
        class loader
    ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader !=
                beanClass.getClassLoader()) {
            classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
        }
    //从代理⼯⼚中获取代理
        return proxyFactory.getProxy(classLoader);
    }
    

    代理工⼚有⼀个重要的属性:proxyTargetClass,默认值为false.

    可以通过程序设置

    proxyTargetClass⽬标对象代理⽅式
    false实现了接⼝jdk代理
    false未实现接⼝(只有实现类)cglib代理
    true实现了接⼝cglib代理
    true未实现接⼝(只有实现类)cglib代理

    可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置

    需要注意的是:

    • Spring Boot 2.X开始,默认使⽤CGLIB代理,可以通过配置项 spring.aop.proxy-target-class=false 来进⾏修改,设置默认为jdk代理

      SpringBoot设置 @EnableAspectJAutoProxy ⽆效,因为Spring Boot默认使⽤AopAutoConfiguration进⾏装配

      @SpringBootApplication
      public class DemoApplication {
          public static void main(String[] args) {
              ApplicationContext context =
                      SpringApplication.run(DemoApplication.class, args);
      /**
       * HouseProxy houseProxy = context.getBean(HouseProxy.class);
       * 设置spring.aop.proxy-target-class=true cglib代理, 运⾏成功
       * 设置spring.aop.proxy-target-class=false jdk代理, 运⾏失败, 不能代理类
       * 因为 HouseProxy 是⼀个类, ⽽不是接⼝, 需要修改为
       * HouseSubject houseProxy = (HouseSubject)
       context.getBean("realHouseSubject")
       *
       */
              HouseProxy houseProxy = context.getBean(HouseProxy.class);
      //HouseSubject houseProxy = (HouseSubject)
              context.getBean("realHouseSubject");//正确运⾏
              System.out.println(houseProxy.getClass().toString());
          }
      }
      

      注意:使⽤context.getBean()需要添加注解,使HouseProxy,RealHouseSubject被Spring管理测试AOP代理,需要把这些类交给AOP管理(⾃定义注解或使用@Aspect)

      我们再看以下代理⼯⼚的代码

      public class ProxyFactory extends ProxyCreatorSupport {
          //...代码省略
      //获取代理
          public Object getProxy(@Nullable ClassLoader classLoader) {
      //分两步 先createAopProxy,后getProxy
              return createAopProxy().getProxy(classLoader);
          }
          protected final synchronized AopProxy createAopProxy() {
              if (!this.active) {
                  activate();
              }
              return getAopProxyFactory().createAopProxy(this);
          }
      //...代码省略
      }
      

      createAopProxy的实现在DefaultAopProxyFactory中

      public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
          //...代码省略
          @Override
          public AopProxy createAopProxy(AdvisedSupport config) throws
                  AopConfigException {
      /**
       * 根据proxyTargetClass判断
       * 如果⽬标类是接⼝, 使⽤JDK动态代理
       * 否则使⽤cglib动态代理
       */
              if (!NativeDetector.inNativeImage() &&
                      (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) ||
                          ClassUtils.isLambdaClass(targetClass)) {
                      return new JdkDynamicAopProxy(config);
                  }
                  return new ObjenesisCglibAopProxy(config);
              }
              else {
                  return new JdkDynamicAopProxy(config);
              }
          }
      //...代码省略
      }
      

      接下来就是创建代理了

      JDK动态代理

      final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
              Serializable {
          //...代码省略
          @Override
          public Object getProxy(@Nullable ClassLoader classLoader) {
              if (logger.isTraceEnabled()) {
                  logger.trace("Creating JDK dynamic proxy: " +
                          this.advised.getTargetSource());
              }
              return Proxy.newProxyInstance(determineClassLoader(classLoader),
                      this.proxiedInterfaces, this);
          }
      //...代码省略
      }
      

      CGLIB动态代理

      class CglibAopProxy implements AopProxy, Serializable {
          //...代码省略
          @Override
          public Object getProxy(@Nullable ClassLoader classLoader) {
              //...代码省略
      // Configure CGLIB Enhancer...
              Enhancer enhancer = createEnhancer();
      // Generate the proxy class and create a proxy instance.
              return createProxyClassAndInstance(enhancer, callbacks);
          }
      //...代码省略
      }
      

      以上就是对Spring AOP源码的一个简单剖析。

      ⭕总结

      关于《【JavaEE进阶】 Spring AOP源码简单剖析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下