SpringBoot AoP(2)@Aspect切面方法查找

677 阅读2分钟

在创建bean的时候,会给后置处理器一个机会来看目标类是否能用代理类替换,如果没有返回代理类的话,会走后面的实例化方法。

AbstractAutowireCapableBeanFactory->applyBeanPostProcessorsBeforeInstantiation():
    // 依次调用后置处理器的postProcessBeforeInstantiation()方法,这里分析为AnnotationAwareAspectJAutoProxyCreator后置处理器的时候
    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
AbstractAutoProxyCreator->postProcessBeforeInstantiation():
    Object cacheKey = getCacheKey(beanClass, beanName);
    // 第一次进来targetSourcedBeans.contains(beanName)肯定为false,走if方法
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // 同理,advisedBeans.containsKey(cacheKey)也返回的是false
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // isInfrastructureClass(beanClass),当beanClass是Advice、Pointcut、Advisor、AopInfrastructureBean类及其子类或者存在@Aspect注解的时候,返回true
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            // advisedBeans是key-value键值对,key是beanName,value为true或者false,代表能该beanClass的实例能否被创建代理
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
// 当isInfrastructureClass(beanClass)返回false的时候,执行shouldSkip(beanClass, beanName)方法
AspectJAwareAdvisorAutoProxyCreator->shouldSkip():
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    ......
    // 只有当beanName以beanClass的全限定名开头,且以.ORIGINAL结尾时,才返回true
    return super.shouldSkip(beanClass, beanName);
AnnotationAwareAspectJAutoProxyCreator->findCandidateAdvisors():
    // 实现了Advisor接口的类,如事务类BeanFactoryTransactionAttributeSourceAdvisor
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 自定义切面类的切面方法
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
     // 返回项目中所有切面类的切面方法信息集合
    return advisors;
BeanFactoryAspectJAdvisorsBuilder->buildAspectJAdvisors():
    // 获取IoC容器中所有beanName
    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Object.class, true, false);
    for (String beanName : beanNames) {
    ......
        // 看beanClass是否有@Aspect注解,此项目中只有OperationAop类返回true,如果是false直接跳过了
        if (this.advisorFactory.isAspect(beanType)) {
            ......
            // 获取单个bean的切面方法信息,添加到advisors集合中
            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);   // --1
            // 根据beanClass是否是单例放入不同的缓存中
            if (this.beanFactory.isSingleton(beanName)) {
                this.advisorsCache.put(beanName, classAdvisors);
            } else {
                this.aspectFactoryCache.put(beanName, factory);
            }
            advisors.addAll(classAdvisors);
        }
    }
    // 最终返回的是所有切面类的切面方法信息集合
    this.aspectBeanNames = aspectNames;
    return advisors;
ReflectiveAspectJAdvisorFactory->getAdvisors(): // --1
    // getAdvisorMethods()返回的是除了@Pointcut注解返回的方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 遍历方法,当方法存在@Pointcut/@Around/@Before/@After/@AfterReturning/@AfterThrowing六个注解其中之一时,会封装成Advisor类对象
        // advisor封装了方法信息、切面信息、切面类信息、IoC容器等信息
        // 返回的实现类是InstantiationModelAwarePointcutAdvisorImpl
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
    // 此项目中,advisors封装了doAround()、doBefore()、doAfter()这三个方法的有关信息,最终返回advisors

总结:

AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation()方法返回目标类的代理类,一般来说这边都是返回空。

满足下列条件之一时,会提前判定不能返回代理类:

  • beanClass是Advice、Pointcut、Advisor、AopInfrastructureBean类及其子类
  • beanClass以@Aspect注解修饰
  • beanName以beanClass的全限定名开头,且以.ORIGINAL结尾

在shouldSkip()方法中,顺便执行了一段找切面方法和初步解析的过程,在Spring阶段只进行一次

想要成为切面类,下面两个条件缺一不可:
1. 能够被扫描成bean
2. 存在@Aspect注解


在自定义切面类里,方法有@Around/@Before/@After/@AfterReturning/@AfterThrowing五个注解之一的,会被解析成切面方法