SpringAOP 如何获取所有的增强器

    在对AOP相关的Bean进行增强的时候,必须要获取增强器,并把增强器应用到到Bean上。那么需要先获取所有的增强器,并构造称为Advisor。

    如何获取构造器那下面,我们从findCandidateAdvisors()进行解析。这个方法的调用位置为,在初始化完成之后调用Bean的后置处理器,处理AOP的动态代理的过程中会多次用到。

1、 AnnotationAwareAspectJAutoProxyCreator.class # findCandidateAdvisors()

protected List findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
//对Advisor.class的处理,现在一般都会采用注解的方式实现、加载配置文件中对AOP的声明
   List advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); //详解 1.2
   return advisors;
}
1、2 th is.aspectJAdvisorsBuilder.buildAspectJAdvisors() // 对注解实现增强类的解析,在第一个Bean初始化的时候就会被调用。
    思路:
        1、获取所有的BeanName,在BeanFactory中所有注册的Bean都会被提取出来
        2、遍历所有的beanName,并找出声明AspectJ注解的类,进一步处理
        3、对标记的类进行增强器的提取。
        4、将提取的结果加入缓存当中。
public List buildAspectJAdvisors() {
   List aspectNames = this.aspectBeanNames;
   if (aspectNames == null) {
      synchronized (this) {
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {
            List advisors = new LinkedList();
            aspectNames = new LinkedList();
            //获取所有的Bean的名字
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                  this.beanFactory, Object.class, true, false);
            //循环所有的Bean,提取出增强器 
           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.
                //我们必须注意不要急于实例化bean,就像在本例中一样,
                //将被Spring容器缓存,但不会被编织。
                //获取Bean对应的类型
               Class beanType = this.beanFactory.getType(beanName);
               if (beanType == null) {
                  continue;
               }
               //被@Aspect标注and was not compiled by ajc
               if (this.advisorFactory.isAspect(beanType)) {
                  aspectNames.add(beanName);
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);//详见上边介绍
                 //正常我们的Aspect类 都是SINGLETON //其他的是AspectJ提供的一些高级的用法 我们这里先不展开 
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                     MetadataAwareAspectInstanceFactory factory =
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                    //解析注解中的增强方法 详见 1.2.1
                     List 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 advisors = new LinkedList();
   for (String aspectName : aspectNames) {
      List 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;
}

1.2.1     getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);//获取增强器

@Override
public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
   //校验类上是否有@Aspect注解
   validate(aspectClass);
   // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
   // so that it will only instantiate once.
   MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

   List advisors = new LinkedList();
    //方法内部会获取所有的方法但是不包含pointcut注解的方法,详见 1.2.1.1
   for (Method method : getAdvisorMethods(aspectClass)) {
      //从这些方法中寻找增强的方法   详见 1.2.1.2
      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()) {
      Advisor advisor = getDeclareParentsAdvisor(field);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }
   return advisors;
}

1.2.1.1  getAdvisorMethods(aspectClass);获取类下面除了@PintCut注解的所有方法

private List getAdvisorMethods(Class aspectClass) {
   final List methods = new LinkedList();
   ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
      @Override
      public void doWith(Method method) throws IllegalArgumentException {
         // Exclude pointcuts
         if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
         }
      }
   });
   Collections.sort(methods, METHOD_COMPARATOR);
   return methods; //16个方法,相见下图
}

SpringAOP 如何获取所有的增强器_第1张图片

1.2.1.2 getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); 从这些方法中寻找增强的方法

@Override
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;
   }
    //根据切点信息生产增强器  详见 1.2.1.2.1
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

//普通增强器的获取
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class candidateAspectClass) {
    //如果方法上存在Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class中的注解时,返回方法上的注解信息。
   AspectJAnnotation aspectJAnnotation =
         AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
   if (aspectJAnnotation == null) {
      return null;
   }
    //构建切点信息并返回
   AspectJExpressionPointcut ajexp =
         new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
   ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
   ajexp.setBeanFactory(this.beanFactory);
   return ajexp;
}

1.2.1.2.1 new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,

         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);//构建增强器

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); //实例化Advice
   }
}
//实例化Advice
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
   return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
         this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}

//对不同的切面方式生产对应的切面实体
@Override
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);
  
   AbstractAspectJAdvice springAdvice;
   switch (aspectJAnnotation.getAnnotationType()) {
      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;
      case AtAround:
         springAdvice = new AspectJAroundAdvice(
               candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
         break;
      case AtPointcut:
         if (logger.isDebugEnabled()) {
            logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
         }
         return null;
      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;
}

 

你可能感兴趣的:(Spring问题,Spring源码解析,spring,java)