Spring AOP 总结二

前面说过:AOP是一种编程思想,用于将程序中的横切关注点(如事务、日志)从业务逻辑代码中分离出来,以提高代码的可重用性和可维护性。Spring框架对其进行了实现。在Spring中AOP是通过代理模式实现的,即在运行时动态的生成一个代理,这个代理类会拦截目标对象的方法调用,并在方法执行前后添加响应的横切逻辑

通过这一段话,我们只能知道Spring框架使用动态代理技术对AOP进行了实现。那Spring究竟是怎么实现的呢?下面就根据源码一步步地揭开Spring AOP的神秘面纱吧。在开始跟踪之前,先来看一个问题吧:假设现在没有实现AOP的Spring框架,公司领导又点名要你给系统增加日志功能,作为开发者你会怎么做(需要说明的是要添加日志的接口非常多,并且这个日志要足够灵活,能够支持后面其他同事开发的新接口。那该怎么高效、安全的实现这个需求呢?答案肯定是AOP!)。思路大概是这样的(这里有点事后诸葛亮,不过还是想通过这个让大家有个基本的认识,以便后面跟踪Spring源码时能够快速理解。该思路参照了字符串搜索表达式,同时用到了反射和动态代理):

  1. 配置匹配模式,即匹配将被增强的方法(即目标方法)
  2. 编写增强方法,即要对目标方法做的增强逻辑,比如本例中的日志打印逻辑
  3. 为目标创建代理,然后使用该代理

参照上述两点,落地开发的详细步骤为:

  1. 匹配模式解析,即将该匹配模式保存下来,以便后面匹配时使用
  2. 增强方法匹配逻辑,即用配置的匹配模式找到要被增强的类或方法,并将其存储在Map中
  3. 增强方法解析及增强方法与匹配模式关系处理,即将增强方法解析出来,并为该增强方法指定一定的匹配模式
  4. 为目标方法创建一个代理,然后在该代理类相关方法的前后设置相关增强方法
  5. 调用代理调用目标方法

这里要注意一下:被增强的方法,即目标方法,是处理实际业务的方法(比如上一节TransferService类中的check(…)方法);匹配模式,即切入点,它是一个字符串表达式,用于匹配合适的目标方法(比如上一节CustomerAspect中的pointcut(…)方法);增强方法,即切面,是对目标方法的扩展,比如日志打印、事务等(比如上一节CustomerAspect类中的around(…)方法、before(…)方法、after(…)方法)

下面我们从@EnableAspectJAutoProxy注解开始跟踪。该注解详细实现代码中有一个注解@Import(AspectJAutoProxyRegistrar.class),通过该注解系统会自动向Spring容器中注入一个类型为AnnotationAwareAspectJAutoProxyCreator的对象。我们先看一下这两个注解的代码实现:

 从这里继续向下跟踪会看到如下图所示的代码:

前面提到过,这里会向容器中注入AnnotationAwareAspectJAutoProxyCreator对象,该类的继承结构如下图所示: 

 从这幅图可以看到AbstractAutoProxyCreator继承了BeanPostProcessor接口。该接口中主要定义了两个方法:

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

由此可知继承该接口的实现类的主要作用是在注册到Spring中的Bean的初始化前后做一些处理,比如本节要讲的代理对象就是在postProcessAfterInitialization()方法中创建的。接下来主要看一下AbstractAutoProxyCreator类中的postProcessAfterInitialization()方法的代码,其代码如下所示:

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
       Object cacheKey = getCacheKey(bean.getClass(), beanName);
       if (this.earlyBeanReferences.remove(cacheKey) != bean) {
// 主要关注这里
          return wrapIfNecessary(bean, beanName, cacheKey);
       }
    }
    return bean;
}

在上面代码中我们主要关注wrapIfNecessary()方法。该方法的代码如下所示:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
       return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
       return bean;
    }
    // 重点关注这个 shouldSkip() 方法,该方法最终会调用BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()以解析@Aspect注解修饰的类,其中用@Around、@After、@Before等注解修饰的方法会被解析
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
    }

    // Create proxy if we have advice.
    // 这段代码的主要逻辑是提取适用该对象的Advice和Advisor。
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
       this.advisedBeans.put(cacheKey, Boolean.TRUE);
       Object proxy = createProxy(
             bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
       this.proxyTypes.put(cacheKey, proxy.getClass());
       return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

对于这个方法我想按照以下顺序梳理:解析(主要解析系统中配置的切面和切点)、创建代理(将符合切点的方法和切面进行组合,并用代理对象包装)。

1 解析

这里主要梳理Spring如何解析用@Aspect修饰的类以及@Around、@After、@Before等注解修饰的方法。下面首先看一下AspectJAwareAdvisorAutoProxyCreator#shouldSkip(Class<?> beanClass, String beanName)方法,其源码如下所示:

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // TODO: Consider optimization by caching the list of the aspect names
    // 该方法的主要作用是查找所有候选的Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
       if (advisor instanceof AspectJPointcutAdvisor pointcutAdvisor &&
             pointcutAdvisor.getAspectName().equals(beanName)) {
          return true;
       }
    }
    return super.shouldSkip(beanClass, beanName);
}

这里主要看findCandidateAdvisors()方法,该方法的源码如下所示(注意这个源码位于AspectJAwareAdvisorAutoProxyCreator类中):

protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

由于Spring容器启动时注入的实际类型为AnnotationAwareAspectJAutoProxyCreator,所以AspectJAwareAdvisorAutoProxyCreator#shouldSkip(Class<?> beanClass, String beanName)中的List<Advisor> candidateAdvisors = findCandidateAdvisors()最终调用的是AnnotationAwareAspectJAutoProxyCreator中的findCandidateAdvisors()方法,其源码如下所示:

@Override
protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
       // 重点关注这里
       advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

这里主要看this.aspectJAdvisorsBuilder.buildAspectJAdvisors()这段代码,该方法位于BeanFactoryAspectJAdvisorsBuilder类中,其源码如下所示:

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
       synchronized (this) {
          aspectNames = this.aspectBeanNames;
          if (aspectNames == null) {
             List<Advisor> advisors = new ArrayList<>();
             aspectNames = new ArrayList<>();
             String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                   this.beanFactory, Object.class, true, false);
             for (String beanName : beanNames) {
                if (!isEligibleBean(beanName)) {
                   continue;
                }
                // We must be careful not to instantiate beans eagerly as in this case they
                // would be cached by the Spring container but would not have been weaved.
                Class<?> beanType = this.beanFactory.getType(beanName, false);
                if (beanType == null) {
                   continue;
                }
                if (this.advisorFactory.isAspect(beanType)) {
                   aspectNames.add(beanName);
                   AspectMetadata amd = new AspectMetadata(beanType, beanName);
                   if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                      MetadataAwareAspectInstanceFactory factory =
                            new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                      List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                      if (this.beanFactory.isSingleton(beanName)) {
                         this.advisorsCache.put(beanName, classAdvisors);
                      }
                      else {
                         this.aspectFactoryCache.put(beanName, factory);
                      }
                      advisors.addAll(classAdvisors);
                   }
                   else {
                      // Per target or per this.
                      if (this.beanFactory.isSingleton(beanName)) {
                         throw new IllegalArgumentException("Bean with name '" + beanName +
                               "' is a singleton, but aspect instantiation model is not singleton");
                      }
                      MetadataAwareAspectInstanceFactory factory =
                            new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                      this.aspectFactoryCache.put(beanName, factory);
                      advisors.addAll(this.advisorFactory.getAdvisors(factory));
                   }
                }
             }
             this.aspectBeanNames = aspectNames;
             return advisors;
          }
       }
    }
    // 下面这段在跟踪的时候没走,所以以下代码暂不梳理
    if (aspectNames.isEmpty()) {
       return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String aspectName : aspectNames) {
       List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
       if (cachedAdvisors != null) {
          advisors.addAll(cachedAdvisors);
       }
       else {
          MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
          advisors.addAll(this.advisorFactory.getAdvisors(factory));
       }
    }
    return advisors;
}

从上述代码可以知道,这段代码会遍历Spring容器中注册的所有beanName,然后判断该bean是否被@Aspect注解修饰,如果是则继续解析,否则跳过,具体如下图所示:

上述代码中的List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory)是真正解析的入口。其代码(位于ReflectiveAspectJAdvisorFactory类中)如下所示:

@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);

    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    // so that it will only instantiate once.
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
          new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    for (Method method : getAdvisorMethods(aspectClass)) {
       // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
       // to getAdvisor(...) to represent the "current position" in the declared methods list.
       // However, since Java 7 the "current position" is not valid since the JDK no longer
       // returns declared methods in the order in which they are declared in the source code.
       // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
       // discovered via reflection in order to support reliable advice ordering across JVM launches.
       // Specifically, a value of 0 aligns with the default value used in
       // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
       Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
       if (advisor != null) {
          advisors.add(advisor);
       }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
       Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
       advisors.add(0, instantiationAdvisor);
    }

    // Find introduction fields.
    for (Field field : aspectClass.getDeclaredFields()) {
       Advisor advisor = getDeclareParentsAdvisor(field);
       if (advisor != null) {
          advisors.add(advisor);
       }
    }

    return advisors;
}

该方法主要做了两件事:1.解析@Aspect注解修饰的类中被@Around、@After、@Before修饰的方法;2.解析@Aspect注解修饰的类中的字段。第一步解析调用的是ReflectiveAspectJAdvisorFactory类中的getAdvisor()方法,该方法主要做了下面几件事:

  1. 校验(个人理解就是校验当前Bean对应的类是否被@Aspect注解修饰)
  2. 解析切入点,即AspectJExpressionPointcut,也就是@Around等注解中指定的切入点
  3. 创建InstantiationModelAwarePointcutAdvisorImpl对象,这里会创建实际的通知类型,即Advice

getAdvisor()方法的主要代码如下所示:

@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
       int declarationOrderInAspect, String aspectName) {

    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    AspectJExpressionPointcut expressionPointcut = getPointcut(
          candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
       return null;
    }

    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
          this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

接下来继续看InstantiationModelAwarePointcutAdvisorImpl构造方法的代码,如下所示:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
       Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
       MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    this.declaredPointcut = declaredPointcut;
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    this.methodName = aspectJAdviceMethod.getName();
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    this.aspectInstanceFactory = aspectInstanceFactory;
    this.declarationOrder = declarationOrder;
    this.aspectName = aspectName;

    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
       // Static part of the pointcut is a lazy type.
       Pointcut preInstantiationPointcut = Pointcuts.union(
             aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

       // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
       // If it's not a dynamic pointcut, it may be optimized out
       // by the Spring AOP infrastructure after the first evaluation.
       this.pointcut = new PerTargetInstantiationModelPointcut(
             this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
       this.lazy = true;
    }
    else {
       // A singleton aspect.
       this.pointcut = this.declaredPointcut;
       this.lazy = false;
       this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
}

主要关注这段代码的最后一行,即调用instantiateAdvice(AspectJExpressionPointcut pointcut)方法的这行,该方法源码如下所示:

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
    Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
          this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
    return (advice != null ? advice : EMPTY_ADVICE);
}

该方法最终会调用AspectJAdvisorFactory类的getAdvice()方法,其源码如下所示:

@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
       MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);

    AspectJAnnotation aspectJAnnotation =
          AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
       return null;
    }

    // If we get here, we know we have an AspectJ method.
    // Check that it's an AspectJ-annotated class
    if (!isAspect(candidateAspectClass)) {
       throw new AopConfigException("Advice must be declared inside an aspect type: " +
             "Offending method '" + candidateAdviceMethod + "' in class [" +
             candidateAspectClass.getName() + "]");
    }

    if (logger.isDebugEnabled()) {
       logger.debug("Found AspectJ method: " + candidateAdviceMethod);
    }

    AbstractAspectJAdvice springAdvice;

    switch (aspectJAnnotation.getAnnotationType()) {
       case AtPointcut -> {
          if (logger.isDebugEnabled()) {
             logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
          }
          return null;
       }
       case AtAround -> springAdvice = new AspectJAroundAdvice(
             candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
       case AtBefore -> springAdvice = new AspectJMethodBeforeAdvice(
             candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
       case AtAfter -> springAdvice = new AspectJAfterAdvice(
             candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
       case AtAfterReturning -> {
          springAdvice = new AspectJAfterReturningAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
          AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
          if (StringUtils.hasText(afterReturningAnnotation.returning())) {
             springAdvice.setReturningName(afterReturningAnnotation.returning());
          }
       }
       case AtAfterThrowing -> {
          springAdvice = new AspectJAfterThrowingAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
          AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
          if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
             springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
          }
       }
       default -> throw new UnsupportedOperationException(
             "Unsupported advice type on method: " + candidateAdviceMethod);
    }

    // Now to configure the advice...
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
       springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

对于这段代码主要关注下图所示的地方(这里会根据枚举类型创建不同的Advice):

至此Spring AOP解析的步骤都梳理完成了。下面继续看一下解析过程中涉及的两个主要角色吧!它们分别为:Advisor、AdviceAdvisor是Spring AOP的顶级接口,上面看到的InstantiationModelAwarePointcutAdvisorImpl就实现了该接口,其包含了通知(Advice)和适用判断的过滤器。考虑到通用性,过滤规则由其子接口定义,比如IntroductionAdvisor和PointcutAdvisor,过滤器用于判断bean是否需要被代理。Advice被称为通知,也即在调用目标方法时我们想要做的处理逻辑,比如处理事务、打印日志等,比如上节示例中提到的前置通知、后置通知和环绕通知等。通过源码也可以知道Spring AOP提供的通知主要有这样几类:AtAround、AtBefore、 AtAfter、AtAfterReturning、AtAfterThrowing。这些都定义在Spring的AspectJAnnotationType枚举中。该枚举的源码如下所示:

protected enum AspectJAnnotationType {
    AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}

下图是Spring AOP常见的几种通知的类结构图:

这里要再明确这样一个点:Advisor包含通知(拦截器),是Spring中AOP的顶级接口,不过这个接口实现类中还需要包含一个aop适用判断的过滤器。考虑到通用性,过滤规则由其子接口定义,比如IntroductionAdvisor和PointcutAdvisor,过滤器用于判断bean是否需要被代理。下面两幅图就展示了IntroductionAdvisor、PointcutAdvisor及其子类的类结构。还记得InstantiationModelAwarePointcutAdvisorImpl对象的创建吧!这里再看以下这段代码: 

AspectJExpressionPointcut expressionPointcut = getPointcut(
       candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
    return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
       this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

下图为Pointcut接口的实现类AspectJExpressionPointcut的类结构图。Pointcut可以被称作切点,是过滤器的一种实现,用于匹配过滤哪些类或哪些方法需要被切面处理,其实现了ClassFilter和MethodMatcher接口。这个类在定义PointcutAdvisor(比如创建上图InstantiationModelAwarePointcutAdvisorImpl类型对象时,会向其构造方法中传递一个AspectJExpressionPointcut类型的对象)类型的对象时会用到。

从上图可以看出AspectJExpressionPointcut实现了ClassFilter和MethodMatcher接口。其中ClassFilter是限制切入点或引入点与给定目标类集的匹配的筛选器,属于过滤器的一种实现。过滤筛选合适的类,有些类不需要被处理。MethodMatcher是方法匹配器,定义方法匹配规则,也是过滤器的一种实现,其主要用于判断哪些方法需要使用AOP。不知道你有没有注意到,AspectJExpressionPointcut类中有这样一段代码:

看着是不是有些熟悉,还记得Spring AOP第一篇中切入点的定义吗?对,就是@Pointcut("execution(* org.com.chinasofti.springtransaction.service.*.*(..))")注解中的execution。这组定义涉及到了切点的定义,这里就不再梳理了,如果想深入了解配置规则,可以参照下面这篇博客:https://www.cnblogs.com/cunkouzh/p/5844816.html

2 创建代理

本小节主要梳理Spring AOP代理类的创建过程。代码入口位于AbstractAutoProxyCreator类的wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法中。如下图所示:

接下来主要关注createProxy(Class<?> beanClass, @Nullable String beanName,    @Nullable Object[] specificInterceptors, TargetSource targetSource)方法的处理逻辑,该方法位于AbstractAutoProxyCreator类中,其详细代码如下所示:

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

    return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);
}

这段代码非常简单,主要是调用AbstractAutoProxyCreator的buildProxy()方法去创建代理,其具体代码如下所示:

private Object buildProxy(Class<?> beanClass, @Nullable String beanName,
       @Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {
       AutoProxyUtils.exposeTargetClass(clbf, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (proxyFactory.isProxyTargetClass()) {
       // Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
       if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
          // Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
          for (Class<?> ifc : beanClass.getInterfaces()) {
             proxyFactory.addInterface(ifc);
          }
       }
    }
    else {
       // No proxyTargetClass flag enforced, let's apply our default checks...
       if (shouldProxyTargetClass(beanClass, beanName)) {
          proxyFactory.setProxyTargetClass(true);
       }
       else {
          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 smartClassLoader && classLoader != beanClass.getClassLoader()) {
       classLoader = smartClassLoader.getOriginalClassLoader();
    }
    return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader));
}

通过代码不难看出,其首先创建一个代理工厂对象,即ProxyFactory proxyFactory = new ProxyFactory(),接着从容器中拿到适配指定beanName的Advisor,即前面提到的包含通知和适配过滤器的对象,这里拿到的是一组对象,其实际类型就是前面提到的InstantiationModelAwarePointcutAdvisorImpl类型(这里参照的是前一节的示例),最后调用ProxyFactory类的getProxy()方法创建代理对象。接下来看一下PoxyFactory类的getProxy()方法,其具体代码如下所示:

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

该类会调用其父类ProxyCreatorSupport类的createAopProxy(),其代码如下所示:

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

这个方法(指的是createproxy())先调用本类中的getAopProxyFactory()方法获取AopProxyFactory类型的对象aopProxyFactory(该对象的初始化实在ProxyCreatorSupport类的构造方法中做的,具体如下图所示)

接着这个方法(指的是createproxy())又继续DefaultAopProxyFactory(该类实现了AopProxyFactory接口)类的createAopProxy()方法,其具体代码如下所示:

@Override
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.");
       }
       if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
          return new JdkDynamicAopProxy(config);
       }
       return new ObjenesisCglibAopProxy(config);
    }
    else {
       return new JdkDynamicAopProxy(config);
    }
}

从这段代码可以看到我们常见的JDK动态代理和CGLIB动态代理。根据debug结果,Spring使用CGLIB来创建目标对象的代理对象,即使用ObjenesisCglibAopProxy对象来创建后面的代理对象。注意该类继承了CglibAopProxy类。接着继续回到PoxyFactory类的getProxy()方法中,继续跟踪到getProxy()方法,此时会跳转到CglibAopProxy类的getProxy()方法中,该方法继续调用本类的buildProxy ()方法。该方法源码如下所示:

private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {
    if (logger.isTraceEnabled()) {
       logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    }

    try {
       Class<?> rootClass = this.advised.getTargetClass();
       Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

       Class<?> proxySuperClass = rootClass;
       if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
          proxySuperClass = rootClass.getSuperclass();
          Class<?>[] additionalInterfaces = rootClass.getInterfaces();
          for (Class<?> additionalInterface : additionalInterfaces) {
             this.advised.addInterface(additionalInterface);
          }
       }

       // Validate the class, writing log messages as necessary.
       validateClassIfNecessary(proxySuperClass, classLoader);

       // Configure CGLIB Enhancer...
       Enhancer enhancer = createEnhancer();
       if (classLoader != null) {
          enhancer.setClassLoader(classLoader);
          if (classLoader instanceof SmartClassLoader smartClassLoader &&
                smartClassLoader.isClassReloadable(proxySuperClass)) {
             enhancer.setUseCache(false);
          }
       }
       enhancer.setSuperclass(proxySuperClass);
       enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
       enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
       enhancer.setAttemptLoad(true);
       enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

       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
       ProxyCallbackFilter filter = new ProxyCallbackFilter(
             this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset);
       enhancer.setCallbackFilter(filter);
       enhancer.setCallbackTypes(types);

       // Generate the proxy class and create a proxy instance.
       // ProxyCallbackFilter has method introspection capability with Advisor access.
       try {
          return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
       }
       finally {
          // Reduce ProxyCallbackFilter to key-only state for its class cache role
          // in the CGLIB$CALLBACK_FILTER field, not leaking any Advisor state...
          filter.advised.reduceToAdvisorKey();
       }
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {
       throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
             ": Common causes of this problem include using a final class or a non-visible class",
             ex);
    }
    catch (Throwable ex) {
       // TargetSource.getTarget() failed
       throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

该方法首先创建了Enhancer对象,然后进行一些属性设置,最后调用createProxyClassAndInstance(enhancer, callbacks))创建对应的代理对象。好了,先到这里吧!先跟大家说声对不起,因为我觉得Spring AOP涉及的知识点和编码逻辑还有很多,认知有限的我,真的无法向大家一一介绍,不过后续我还会根据需要对此知识点进行持续更新,也欢迎大家对文章中的不足提出宝贵的意见。在这里先谢谢了!

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器挖掘工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值