#更文挑战#Spring&SpringBoot源码系列 | AOP代理类的创建过程

170 阅读4分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」 前言 本篇文章会介绍Spring中AOP的代理Bean的创建过程,对于AOP大家或多或少的都有些了解,无非就是创建代理,横切逻辑插入到目标方法执行的前后,原理就是如此,但是在实现上却十分复杂,下面一起看下 首先介绍下AOP的相关概念

  • Aspect :切面,切入系统的一个切面,比如事务管理是一个切面
  • Join point :连接点,也就是可以进行横向切入的位置
  • Advice :通知,切面在某个连接点执行的操作(分为: Before advice,After returning advice, After throwing advice,After (finally) advice,Around advice )
  • Pointcut :切点,符合切点表达式的连接点,也就是真正被切入的地方 之前在Bean的加载流程提到过,在createBean的过程中会调用一次resolveBeforeInstantiation()方法来返回一个代理的Bean,AOP的核心是 AnnotationAwareAspectJAutoProxyCreator类,如下图所示: image.png 上图可知又是BeanPostProcessor的实现类 具体的实现方法是在AbstractAutoProxyCreator中,也就是Bean加载过程中要经过 AbstractAutoProxyCreator.postProcessBeforeInstantiation(),postProcessAfterInitialization(),两个方法。
 public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
     //省略
 }
return null;
  }
 @Override
 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
     if (bean != null) {
         //beanName;
         Object cacheKey = getCacheKey(bean.getClass(), beanName);
         //todo earalyProxy 是用来缓存提前暴露对象的缓存key
         if (!this.earlyProxyReferences.contains(cacheKey)) {
             //创建代理Bean
             return wrapIfNecessary(bean, beanName, cacheKey);
         }
     }
     return bean;
 }

本文主要从postProcessAfterInitialization开始描述,重点关注入口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;
    }
    //@1.1 给定的bean类是否Advice,Pointcut,Advisor,AopInfrastructureBean等这些类不需要被代理,
    //@1.2 或是指定的bean不需要被代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    //@1.3 获取增强器
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //要是获取到了增强则需要针对增强进行代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //@1.4 这里创建代理
        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;
}

上述代码可知创建一个代理对象大致流程为:

  • 判断是否是特殊的Bean的类型,以及是否跳过.
  • 获取增强器
  • 创建代理Bean 主要分为三个过程,看着很简单的过程但是这三个流程是十分十分十分十分复杂的,下边开始一点一点的分析。

@1.1 isInfrastructureClass

protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
            Pointcut.class.isAssignableFrom(beanClass) ||
            Advisor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass);
    return retVal;
}

如果是Advice,Pointcut,Advisor,AopInfrastructureBean类型的bean就跳过

@1.2  shouldSkip()

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
   // @1.2.1 获取所有的的Advisor增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor &&
                ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

@1.2.1 findCandidateAdvisors() 获取增强器

@Override
protected List<Advisor> findCandidateAdvisors() {
    //@1.2.1.1这一步其实就是获取Spring配置文件中定义的Advisor
    //或者被@Bean注解标识的Advisor例如BeanFactoryCacheOperationSourceAdvisor
    //和事务相关的BeanFactoryTransactionAttributeSourceAdvisor都是这一步获取到
    List<Advisor> advisors = super.findCandidateAdvisors();
    //@1.2.1.2 解析 @Aspect 注解,并构建通知器合并到List
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

@1.2.1.1  findCandidateAdvisors()

@Override
protected List<Advisor> findCandidateAdvisors() {
    //@1.2.1.1这一步其实就是获取Spring配置文件中定义的Advisor
    //或者被@Bean注解标识的Advisor例如BeanFactoryCacheOperationSourceAdvisor
    //和事务相关的BeanFactoryTransactionAttributeSourceAdvisor都是这一步获取到
    List<Advisor> advisors = super.findCandidateAdvisors();
    //@1.2.1.2 解析 @Aspect 注解,并构建通知器合并到List
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

从这个类中大致能猜出findCandidateAdvisors()是干嘛的,就是从BeanFactory中获取Advisor类型的Bean,下边具体分下这个方法

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<>();
                aspectNames = new LinkedList<>();
                //获取所有的beanName IOC定义的所有的Beanname
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                //循环找出增强
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                        //获取对应的bean类型
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        if (this.advisorFactory.isAspect(beanType)) {
                            //存入到list中
                            aspectNames.add(beanName);
                            //封装切面元数据
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                //@1.2.1.2.1 获取增强器
                                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 {
                                //.........
                            } } }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }
        if (aspectNames.isEmpty()) {
            return Collections.emptyList();
        }
        List<Advisor> advisors = new LinkedList<>();
        for (String aspectName : aspectNames) {
            //这里获取单例的Advisor
            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;
    }

上边代码就是从容器中获取增强类的逻辑大致流程就是

  • 判断是否有缓存的advisorNames,如果没有从容器中获取所有ClassType为Advisor的BeanName
  • 遍历advisorNames并获取到对应Bean 接着继续分析buildAspectJAdvisor() 获取@Aspect注解标识的Advisor

@1.2.1.2 buildAspectJAdvisor()

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<>();
                aspectNames = new LinkedList<>();
                //获取所有的beanName IOC定义的所有的Beanname
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                //循环找出增强
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                        //获取对应的bean类型
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        if (this.advisorFactory.isAspect(beanType)) {
                            //存入到list中
                            aspectNames.add(beanName);
                            //封装切面元数据
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                //@1.2.1.2.1 获取增强器
                                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 {
                                //.........
                            } } }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }
        if (aspectNames.isEmpty()) {
            return Collections.emptyList();
        }
        List<Advisor> advisors = new LinkedList<>();
        for (String aspectName : aspectNames) {
            //这里获取单例的Advisor
            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;
    }

总结下大概逻辑

  • 从IOC容器中获取所有的BeanName
  • 遍历BeanName数组,获取对应Bean的classType
  • 判断当前Class是否被@Aespect注解标识,如果不是则跳过
  • 调用getAdvisors()获取增强
  • return 最后,源码研究得有耐心,加油!