SpringAop五、AnnotationAwareAspectJAutoProxyCreator处理器前置方法

本文聚焦于SpringAop中的AnnotationAwareAspectJAutoProxyCreator处理器,特别是其`postProcessBeforeInstantiation`前置方法。文章介绍了如何判断Bean是否需要被代理,并详细讲解了缓存、通知器的收集以及Advisor实例的创建过程,包括从ReflectiveAspectJAdvisorFactory获取Advisor的方法。整个分析揭示了SpringAop在Bean实例化前的准备工作,为后续的AOP代理提供了基础。
摘要由CSDN通过智能技术生成

先上一个AnnotationAwareAspectJAutoProxyCreator处理器的类图
在这里插入图片描述
主要关注左半部分处理器接口,重点是InstantiationAwareBeanPostProcessor接口定义的postProcessBeforeInstantiation和postProcessAfterInstantiation方法,即Bean实例化前和实例化后处理方法。

postProcessBeforeInstantiation前置方法

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   Object cacheKey = getCacheKey(beanClass, beanName);

   //查缓存,是否有处理过了,不管是不是需要通知增强的,只要处理过了就会放里面
   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      // isInfrastructureClass 是否是内部基础类 -- Advice  Pointcut Advisor AopInfrastructureBean
      // 是否有@Aspect注解 、就是没有ajc$开头的属性名
      // shouldSkip 找出Aspect切面和解析通知器的方法,通知器Advisor里面有通知Advice实例
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         //要跳过的直接设置FALSE
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }
   return null;
}

这里关注shouldSkip方法,就是判断当前bean是否需要被代理。里面会收集所有通知器并缓存起来。

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
   // TODO: Consider optimization by caching the list of the aspect names
   // findCandidateAdvisors寻找通知器
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   for (Advisor advisor : candidateAdvisors) {
      // 如果当前类是通知器类了,则返回true,外面需要advised的缓存设置为false,标识通知器类是不需要被处理的。
      // 也就是说,如果定义的pointcut范围内包含Aspect的定义类,该类不会被切面处理
      if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
         return true;
      }
   }
   return super.shouldSkip(beanClass, beanName);
}

@Override
protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   // 父类的,先找是否已存在Advisor的bean定义,有的话创建出来添加到集合中。
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {
      //寻找@Aspect注解的切面对象,然后解析他的方法,通过注解来生成对应的通知器Advisor
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}

父类的findCandidateAdvisors方法主要是Spring内置的,可以暂时不用关心,spring事务的通知器是在这里注入的。重点是

this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 这句

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<>();
           //寻找所有object类型的bean定义名字
           String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                 this.beanFactory, Object.class, true, false);
           //遍历获取有Aspect注解的加入到aspectNames列表
           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);
              if (beanType == null) {
                 continue;
              }
              // 判断bean是否被@Aspect注解注释,如果是,代表是一个切面定义类
              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);
                    // 这里解析对应的切面配置,就是反射遍历方法列表,找到除@Pointcut注解的方法
                    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;
}

说明两点:

  • 有缓存,也就是说只会加载一次。写入到缓存map中后,后面都是尽量从map中取
  • 通过advisorFactory工厂获取对应的Advisor实例

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors

/**
 1. 获取切面类型,然后获取除Pointcut注解的所有方法,根据方法注解来创建Advisor通知器
 */
@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<>();
   //getAdvisorMethods获取通知器方法 非Pointcut注解的
   for (Method method : getAdvisorMethods(aspectClass)) {
      //创建Advisor
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), 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()) {
      // @DeclareParents注解的属性
      Advisor advisor = getDeclareParentsAdvisor(field);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }

   return advisors;
}

这里看几个方法:

  1. getAdvisorMethods(aspectClass)
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
   final List<Method> methods = new ArrayList<>();
   // doWithMethods包含父类
   ReflectionUtils.doWithMethods(aspectClass, method -> {
      // Exclude pointcuts
      if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
         methods.add(method);
      }
   });
   // 做了个排序 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class, 普通的方法
   methods.sort(METHOD_COMPARATOR);
   return methods;
}

剔除了@Pointcut注解的方法 – Pointcut切面定义是为了匹配时使用,在后面匹配的时候会加载,这里只是加载Advisor方法,故需要剔除

排序,这里定义了各种Advisor的排序规则

2.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)

@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;
   }

   // 建立method和所对应的pointcut方法的关系, 比如测试的类中doAround方法->doService()
   // 也就是说Advisor通知器只是切面方法和切面定义的关系,
   // pointcut表达式的解析不在这里,就是PointcutExpression还没有赋值
   // 解析这部分是在后面使用时,获取方法匹配器前解析

   // 构造方法里有个instantiateAdvice 初始化Advice通知对象
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

看一下Advice的初始化方法,里面有创建Advisor的
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#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;

   //通知类型
   // 通知对象最后被定义为AspectJAroundAdvice AspectJMethodBeforeAdvice
   // AspectJAfterAdvice AspectJAfterReturningAdvice AspectJAfterThrowingAdvice
   // 这5种类型 AOP最终都是这5类做的增强
   switch (aspectJAnnotation.getAnnotationType()) {
      case AtPointcut:
         if (logger.isDebugEnabled()) {
            logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
         }
         return null;
      case AtAround:
         springAdvice = new AspectJAroundAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         break;
      case AtBefore:
         springAdvice = new AspectJMethodBeforeAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         break;
      case AtAfter:
         springAdvice = new AspectJAfterAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         break;
      case AtAfterReturning:
         springAdvice = new AspectJAfterReturningAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
         if (StringUtils.hasText(afterReturningAnnotation.returning())) {
            springAdvice.setReturningName(afterReturningAnnotation.returning());
         }
         break;
      case AtAfterThrowing:
         springAdvice = new AspectJAfterThrowingAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
         if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
            springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
         }
         break;
      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;
}

可以看到每一种类型对应一个Advisor

至此前置方法基本分析完了,总结一下就是加载Aspect类,解析生成对应的Advisor实例放入缓存供后续使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值