Spring AOP原理分析(四)--AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation源码解析

目录

一、简介

二、AbstractAutoProxyCreator#postProcessBeforeInstantiation源码解析

三、总结


一、简介

AnnotationAwareAspectJAutoProxyCreator 实现了几个重要的扩展接口:

  • 1)、实现了 BeanPostProcessor 接口:实现了 postProcessAfterInitialization()方法;
  • 2)、实现了 InstantiationAwareBeanPostProcessor 接口:实现了 postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法;
  • 3)、实现了 SmartInstantiationAwareBeanPostProcessor 接口:实现了 predictBeanType() 方法;getEarlyBeanReference()方法;
  • 4)、实现了 BeanFactoryAware 接口,实现了 setBeanFactory()方法;

本篇文章主要分析AnnotationAwareAspectJAutoProxyCreator 通过间接实现InstantiationAwareBeanPostProcessor接口,在内部主要做了哪些事情?

二、AbstractAutoProxyCreator#postProcessBeforeInstantiation源码解析

AnnotationAwareAspectJAutoProxyCreator类最上面的父类AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,而SmartInstantiationAwareBeanPostProcessor接口继承自InstantiationAwareBeanPostProcessor,在IOC源码中,我们介绍过,InstantiationAwareBeanPostProcessor内部提供了两个方法:

  • postProcessBeforeInstantiation():在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走;
  • postProcessAfterInstantiation():在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null;

InstantiationAwareBeanPostProcessor是在AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()中执行的,在doCreateBean()实例化bean之前就调用了。

所以,我们需要关注:

AnnotationAwareAspectJAutoProxyCreator

        ==> AspectJAwareAdvisorAutoProxyCreator

                ==> AbstractAdvisorAutoProxyCreator

                        ==> AbstractAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator各个间接父类中,postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法的实现过程。

查看上面四个类的源码,发现只有根父类--- AbstractAutoProxyCreator实现了postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法,我们查看具体的实现过程:

  • (一)、postProcessBeforeInstantiation()方法
// AbstractAutoProxyCreator#postProcessBeforeInstantiation
// postProcessBeforeInstantiation()方法在bean实例化之前调用
// 在创建Bean的流程中还没调用构造器来实例化Bean的时候进行调用(实例化前后)
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 组装缓存key
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // 如果advisedBeans缓存中已经存在,即当前正在创建的Bean已经被解析过,则直接返回null
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }

        // 注意:AnnotationAwareAspectJAutoProxyCreator重写了isInfrastructureClass()方法.

        // 1.isInfrastructureClass():判断当前正在创建的Bean是否是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)
        // 2.shouldSkip():判断是不是应该跳过
        // 满足两个条件其中之一,都将跳过,直接返回null
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            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 targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        // 获取目标对象的拦截器链
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        // 创建AOP代理
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

AbstractAutoProxyCreator#postProcessBeforeInstantiation()处理流程大体如下:

  1. 根据beanClass和beanName获取缓存Key,通常就是beanName,如果是FactoryBean的话,则是"&"+beanNmae;
  2. 判断当前正在创建的Bean是否已经被解析过,如果已解析,则直接返回null;
  3. 判断当前正在创建的Bean是否是基础的Bean、是否需要跳过等;
  4. 用户自定义TargetSource(目标源)的处理;

AbstractAutoProxyCreator#postProcessBeforeInstantiation()中核心就是下面两个方法:

  • isInfrastructureClass(beanClass)方法

此方法主要判断当前正在创建的Bean是否是基础的Bean,即当前bean是否是Advice、PointCut、Advisor、AopInfrastructureBean。

注意AnnotationAwareAspectJAutoProxyCreator类重写了isInfrastructureClass()方法,真正执行的是下面的代码。

// AnnotationAwareAspectJAutoProxyCreator.isInfrastructureClass
protected boolean isInfrastructureClass(Class<?> beanClass) {
    // isInfrastructureClass():判断当前正在创建的Bean是否是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)
    // 或者是否是切面(@Aspect)
    return (super.isInfrastructureClass(beanClass) ||
            (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}

// AbstractAutoProxyCreator.isInfrastructureClass
// 判断当前bean是否是基础类,如Advice、Pointcut、Advisor、AopInfrastructureBean
protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
        Pointcut.class.isAssignableFrom(beanClass) ||
            Advisor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass);
    if (retVal && logger.isTraceEnabled()) {
        logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
    }
    return retVal;
}

// 判断是否切面类
public boolean isAspect(Class<?> clazz) {
    return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

// 判断是否使用@Aspect注解
private boolean hasAspectAnnotation(Class<?> clazz) {
    return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

可以看到,AnnotationAwareAspectJAutoProxyCreator的isInfrastructureClass()方法除了判断当前正在创建的Bean是否是基础的Bean之外,还判断了当前bean是否是切面。

  • shouldSkip(beanClass, beanName)方法

判断是否需要跳过。

// AbstractAutoProxyCreator.shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

注意,AbstractAutoProxyCreator的子类----AspectJAwareAdvisorAutoProxyCreator重写了shouldSkip()方法,而AnnotationAwareAspectJAutoProxyCreator又继承自AspectJAwareAdvisorAutoProxyCreator类。

下面我们看下AspectJAwareAdvisorAutoProxyCreator#shouldSkip()方法的源码:

// AspectJAwareAdvisorAutoProxyCreator.shouldSkip
// 判断是否需要跳过
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 1.获取所有候选的Advisor增强器(即切面里面的通知方法),每个封装的通知方法的增强器的类型为InstantiationModelAwarePointcutAdvisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();

    // 2.循环所有的增强器(通知方法),判断是否是AspectJPointcutAdvisor类型的,如果是的话,则需要跳过。(实际上就是跳过切面类)
    for (Advisor advisor : candidateAdvisors) {
        // 判断每个增强器是否是AspectJPointcutAdvisor类型的, 如果是的话则跳过(跳过切面类)
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }

    // 3.调用父类(AbstractAutoProxyCreator)的shouldSkip()方法
    return super.shouldSkip(beanClass, beanName);
}

shouldSkip()方法的处理流程大体如下:

  1. 获取所有候选的Advisor增强器(即切面里面的通知方法),每个封装的通知方法的增强器的类型为InstantiationModelAwarePointcutAdvisor;
  2. 循环所有的增强器(通知方法),判断是否是AspectJPointcutAdvisor类型的,如果是的话,则需要跳过。(实际上就是跳过切面类);
  3. 调用父类(AbstractAutoProxyCreator)的shouldSkip()方法;

下面我们看一下Spring是如何获取所有候选的Advisor增强器的(即切面里面的通知方法),具体在findCandidateAdvisors()方法,源码如下:

// AbstractAdvisorAutoProxyCreator.findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    // 获取所有候选的Advisor增强器集合
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

AnnotationAwareAspectJAutoProxyCreator类重写了此方法:

// AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.

    // 1.调用父类AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法找到所有候选的增强器(通知方法)
    List<Advisor> advisors = super.findCandidateAdvisors();

    // Build Advisors for all AspectJ aspects in the bean factory.

    // 2.为bean工厂中的所有的AspectJ切面构建Advisor增强器
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()处理过程大体如下:

  1. 调用父类AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法找到所有候选的增强器(通知方法);
  2. 为bean工厂中的所有的AspectJ切面构建Advisors增强器;

首先来看下如何找到所有候选的增强器(通知方法)的,具体源码在BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():

// BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
// 获取所有符合条件的Advisor增强器,会忽略FactoryBeans以及正在创建中的bean
public List<Advisor> findAdvisorBeans() {
    // 1.保存增强器对应的beanName集合,并将cachedAdvisorBeanNames缓存的值赋值给它
    String[] advisorNames = this.cachedAdvisorBeanNames;

    // 2.如果cachedAdvisorBeanNames缓存为空,则从bean工厂中获取class类型为Advisor的所有bean名称
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);

        // 3.存入缓存中
        this.cachedAdvisorBeanNames = advisorNames;
    }

    // 如果advisorNames是空的,直接返回空集合
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();

    // 4.循环遍历前面确定好的增强器对应的beanName集合,确定切面与当前beanName是否符合
    for (String name : advisorNames) {
        // isEligibleBean(): 确定切面与当前beanName是否符合,默认都是true
        if (isEligibleBean(name)) {
            // 5.如果当前bean正在创建中的话,什么都不处理
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            } else {
                try {
                    // 6.根据beanName从工厂中获取对应的bean对象,并添加到advisors集合中
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                } catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Skipping advisor '" + name +
                                             "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }

    // 7.返回advisors增强器集合
    return advisors;
}

findAdvisorBeans()方法的整体流程如下:

  1. 获取到cachedAdvisorBeanNames缓存;
  2. 如果cachedAdvisorBeanNames缓存为空,则从bean工厂中获取class类型为Advisor的所有bean名称;
  3. 将上一步获取的bean名称存入缓存中;循环
  4. 遍历前面确定好的增强器对应的beanName集合,确定切面与当前beanName是否符合;
  5. 如果当前bean正在创建中的话,什么都不处理;
  6. 如果当前bean不是正在创建,则根据beanName从工厂中获取对应的bean对象,并添加到advisors集合中;
  7. 返回advisors增强器集合;

当所有候选的增强器找到之后,就需要为bean工厂中的所有的AspectJ切面构建Advisor增强器,具体是在this.aspectJAdvisorsBuilder.buildAspectJAdvisors()完成的。

// BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
    // 1.获取aspectBeanNames缓存,如果为空,则会触发切面的解析工作
    List<String> aspectNames = this.aspectBeanNames;

    // 解析切面,注意实例化第一个单实例bean的时候就会触发解析切面
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                // 用于保存所有解析出来的Advisor增强器
                List<Advisor> advisors = new ArrayList<>();
                // 用于保存切面名称
                aspectNames = new ArrayList<>();
                // 2.获取工厂中所有的beanNames(bean名称集合)
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Object.class, true, false);

                // 3.循环所有的beanNames(bean名称集合),找到增强器
                for (String beanName : beanNames) {

                    // 跳过不符合条件的beanName
                    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.

                    // 获取beanName对应的bean的类型
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }

                    // 4.如果存在@Aspect注解的话,则进行解析
                    if (this.advisorFactory.isAspect(beanType)) {
                        // 如果是切面类的话,则将beanName加入到aspectNames中
                        aspectNames.add(beanName);

                        // 根据beanType、beanName创建切面元数据
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);

                        // 如果获取per-clause的类型是SINGLETON
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // 创建MetadataAwareAspectInstanceFactory,主要用来创建切面对象实例
                            MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // 5.获取标记了@AspectJ相关注解的增强方法
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

                            if (this.beanFactory.isSingleton(beanName)) {
                                // 6.如果当前bean是单例的,则将对应的增强方法加入advisorsCache缓存中
                                this.advisorsCache.put(beanName, classAdvisors);
                            } else {
                                // 7.如果当前bean不是单例的,则将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法
                                this.aspectFactoryCache.put(beanName, factory);
                            }

                            // 将解析的增强器添加到advisors集合中
                            advisors.addAll(classAdvisors);
                        } else {
                            // 如果per-clause的类型不是SINGLETON
                            // 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);
                            // 将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法
                            this.aspectFactoryCache.put(beanName, factory);
                            // 获取标记@AspectJ注解的增强方法
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                // 将解析出来的切面beanName放到缓存aspectBeanNames
                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }
    }

    // 如果经过上述的解析后,缓存aspectNames还是空列表的话,则直接返回一个空列表出去
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }

    // 存放所有的增强器的集合
    List<Advisor> advisors = new ArrayList<>();

    // 8.循环遍历所有解析到的切面名称
    for (String aspectName : aspectNames) {
        // 9.根据切面名称从缓存advisorsCache中查找对应的增强器
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            // 10.如果缓存中已经存在解析好的Advisor,则直接添加到advisors中
            advisors.addAll(cachedAdvisors);
        } else {
            // 11.缓存中没有,则根据切面beanName从缓存aspectFactoryCache中查找对应的工厂,然后解析出增强器,并添加到advisors中
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    // 返回增强器集合
    return advisors;
}

buildAspectJAdvisors()方法的处理流程:

  1. 获取aspectBeanNames缓存,如果为空,则会触发切面的解析工作;
  2. 获取工厂中所有的beanNames(bean名称集合);
  3. 循环所有的beanNames(bean名称集合),找到增强器;
  4. 如果存在@Aspect注解的话,则进行解析;
  5. 获取标记了@AspectJ相关注解的增强方法;
  6. 如果当前bean是单例的,则将对应的增强方法加入advisorsCache缓存中;
  7. 如果当前bean不是单例的,则将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法;
  8. 循环遍历所有解析到的切面名称,根据切面名称从缓存advisorsCache中查找对应的增强器;
  9. 如果缓存中已经存在解析好的Advisor,则直接添加到advisors中;
  10. 缓存中没有,则根据切面beanName从缓存aspectFactoryCache中查找对应的工厂,然后解析出增强器,并添加到advisors中;

上述流程中,比较复杂的方法是this.advisorFactory.getAdvisors(factory):真正的去获取Advisor增强器。

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors
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, 保证只会实例化一次
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
        new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    // 存放增强器的集合
    List<Advisor> advisors = new ArrayList<>();

    // 获取切面类中的所有通知方法,也就是被@Around、@After等注解修饰的方法,但是会跳过@Pointcut修饰的通知方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 循环解析切面中的通知方法,将通知方法包装成Advisor增强器
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            // 如果增强器不为空,则添加到advisors集合中
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    // 如果增强器advisors不为空,而且配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        // 添加到集合中第一个位置
        advisors.add(0, instantiationAdvisor);
    }

    // 获取DeclareParents注解
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

getAdvisors()方法核心逻辑有两个:

  • 获取切面类中的所有通知方法,并按照规则排序---getAdvisorMethods(aspectClass)方法

也就是被@Around、@After等注解修饰的方法,但是会跳过@Pointcut修饰的通知方法,源码如下:

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisorMethods
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    // 1.获取到当前切面类aspectClass的所有通知方法
    final List<Method> methods = new ArrayList<>();

    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // 2.排除掉@Pointcut注解修饰的方法
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    }, ReflectionUtils.USER_DECLARED_METHODS);

    // 3.对通知方法进行排序
    if (methods.size() > 1) {
        methods.sort(METHOD_COMPARATOR);
    }

    // 4.返回通知方法
    return methods;
}

  • 将通知方法包装成Advisor增强器---getAdvisor()方法
// 将通知方法包装成Advisor增强器
// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                          int declarationOrderInAspect, String aspectName) {

    // 对切面类进行一些校验
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    // 获取切点信息,封装成AspectJExpressionPointcut
    AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }

    // 实例化切面通知对象
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

getAdvisor()核心就是实例化了一个InstantiationModelAwarePointcutAdvisorImpl切面通知对象,我们查看其构造方法:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
                                                  Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
                                                  MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // 切点表达式
    this.declaredPointcut = declaredPointcut;
    // 切面的class对象
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    // 切面方法的名称
    this.methodName = aspectJAdviceMethod.getName();
    // 切面方法的参数类型
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    // 切面方法对象
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    // aspectj的通知工厂
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    // aspect的实例工厂
    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 {
        // 非延迟加载
        this.pointcut = this.declaredPointcut;
        this.lazy = false;
        // 实例化Advice通知对象
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
}

在InstantiationModelAwarePointcutAdvisorImpl的构造方法中,首先是初始化了一些属性值,然后判断当前的切面对象是否需要延时加载,分别做不同的操作。

如果切面对象是非延迟加载的情况,则会执行实例化Advice通知对象:instantiateAdvice(this.declaredPointcut)。

// org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice
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);
}

继续跟踪到this.aspectJAdvisorFactory.getAdvice()方法:

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice
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);
    // 判断解析出来的注解信息是否为null
    if (aspectJAnnotation == null) {
        return null;
    }

    // If we get here, we know we have an AspectJ method.
    // Check that it's an AspectJ-annotated class

    // 再次校验切面类是否使用了@AspectJ注解
    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;

    // 根据方法使用的aspectJ注解创建对应的增强器
    switch (aspectJAnnotation.getAnnotationType()) {
            // 如果是PointCut注解,那么就抛出异常
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
            // 如果是@Around环绕通知,则构建AspectJAroundAdvice通知
        case AtAround:
            springAdvice = new AspectJAroundAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
            // 如果是@Before前置通知,则构建AspectJMethodBeforeAdvice通知
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
            // 如果是@After后置通知,则构建AspectJAfterAdvice通知
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
            // 如果是@AfterReturning返回通知,则构建AspectJAfterReturningAdvice通知
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
            // 如果是@AfterThrowing异常通知,则构建AspectJAfterThrowingAdvice通知
        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);
    }

    // 配置通知对象的相关属性,如设置切面名称、参数等
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

到这里,postProcessBeforeInstantiation()方法整个流程执行完成,已经获取到我们的Advisor增强器。

  • (二)、postProcessAfterInstantiation()方法:直接返回true
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    return true;
}

三、总结

最后,通过一张图总结一下AnnotationAwareAspectJAutoProxyCreator实现InstantiationAwareBeanPostProcessor接口底层做的一些工作:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值