br/>本系列文章:
读源码,我们可以从第一行读起
你知道Spring是怎么剖析设置类的吗?
设置类为什么要添加@ConfIGuration注解?
谈谈Spring中的工具跟Bean,你知道Spring怎么建立工具的吗?
这篇文章,我们来谈一谈Spring中的属性注入
Spring中AOP相关的API及源码剖析,原来AOP是这样子的
推荐阅读:
Spring官网阅读 | 总结篇
Spring杂谈
本系列文章将会带你一行行的将Spring的源码吃透,推荐阅读的文章是阅读源码的基础!”

在上篇文章中(Spring中AOP相关的API及源码剖析,原来AOP是这样子的)我们已经剖析过了AOP的实现的源码,那么Spring是若何将AOP应用到Bean的生命周期的呢?这篇文章就带着人人来探讨下这个问题。本文我们要剖析的代码照样位于org.springframework.beans.factory.support.AbstractAutowireCapABLeBeanFactory#doCreateBean这个方式中,在《我们来谈一谈Spring中的属性注入 》这篇文章中,我们已经剖析过了populateBean这个方式,

以是本文我们接着来看看initializeBean这个方式,它主要干了这么几件事

  1. 执行Aware接口中的方式
  2. 执行生命周期回调方式
  3. 完成AOP署理

对应源码如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  if (System.getSecurityManager() != null) {
   AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    invokeAwareMethods(beanName, bean);
    return null;
   }, getAccessControlContext());
  }
  else {

            // 执行Aware接口中的方式
   invokeAwareMethods(beanName, bean);
  }

  Object wrappedBean = bean;
  if (mbd == null || !mbd.isSynthetic()) {

            // 挪用InitDestroyAnnotatioNBeanPostProcessor
            // 的postProcessBeforeInitialization方式
            // 处置@PostContructor注解标注的方式
            // 另外有一部门aware方式也是在这里挪用的
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  }

  try {
            // 若是实现了InitializingBean,会挪用afterPropertiesSet方式
            // 若是XML中设置了init-method属性,会挪用对应的初始化方式
   invokeInitMethods(beanName, wrappedBean, mbd);
  }
  catch (Throwable ex) {
   throw new BeanCreationException(
     (mbd != null ? mbd.getResourceDescription() : null),
     beanName, "Invocation of init method failed", ex);
  }
  if (mbd == null || !mbd.isSynthetic()) {
            // 在这里完成AOP
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  }

  return wrappedBean;
 }

由于在Spring官网阅读(九)Spring中Bean的生命周期(上)文章中我们已经对这个方式做过剖析了,而且这个方式自己也对照简单,以是不再对这个方式做过多赘述,我们主要关注的就是Spring是若何将AOP应用到Bean的生命周期中的,对应的就是applyBeanPostProcessorsAfterInitialization这个方式,其源码如下:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

现实上就是挪用了所有后置处置器的postProcessAfterInitialization方式,在Spring中AOP相关的API及源码剖析,原来AOP是这样子的一文中已经提到过了,@EnableAspectJAutoProxy注解现实上就是向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator,这个类自己就是一个后置处置器,AOP署理就是由它在这一步完成的。

Bean生命周期中AOP的流程

1、@EnableAspectJAutoProxy

通过@EnableAspectJAutoProxy注解向容器中注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它自己也是一个BeanPostProcessor,这个BeanDefinition会在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors这个方式中完成建立,如下图所示

2、postProcessBeforeInstantiation方式执行

执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方式,现实上就是父类AbstractAutoProxyCreator的postProcessBeforeInstantiation被执行

对应源码如下:

//  这个方式的主要目的就是在不思量通知的情况下,确认哪些Bean不需要被署理
//  1.ADVice,Advisor,Pointcut类型的Bean不需要被署理
//  2.不是原始Bean被包装过的Bean不需要被署理,例如ScopedProxyFactoryBean
//  现实上并不只是这些Bean不需要被署理,若是没有对应的通知需要被应用到这个Bean上的话
//  这个Bean也是不需要被署理的,只不过不是在这个方式中处置的。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);
    // 若是beanName为空或者为这个bean提供了定制的targetSource
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // advisedBeans是一个map,其中key是BeanName,value代表了这个Bean是否需要被署理
        // 若是已经包含了这个key,不需要在举行判断了,直接返回即可
        // 由于这个方式的目的就是在实例化前就确认哪些Bean是不需要举行AOP的
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 说明还没有对这个Bean举行处置
        // 在这里会对SpringAOP中的基础设施bean,例如Advice,Pointcut,Advisor做符号
        // 标志它们不需要被署理,对应的就是将其放入到advisedBeans中,value设置为false
        // 其次,若是这个Bean不是最原始的Bean,那么也不举行署理,也将其value设置为false
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 是否为这个Bean提供了定制的TargetSource
    // 若是提供了定制的TargetSource,那么直接在这一步建立一个署理工具并返回
    // 一样平常不会提供
    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;
}

3、postProcessAfterInitialization方式执行
现实上也是执行父类AbstractAutoProxyCreator中的方式,对应源码如下:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 什么时刻这个判断会建立呢?
        // 若是不泛起循环引用的话,remove方式肯定返回null
        // 以是这个remove(cacheKey) != bean肯定会建立
        // 若是发生循环依赖的话,这个判断就不会建立
        // 这个我们在先容循环依赖的时刻再详细剖析,
        // 现在你只需要知道wrapIfNecessary完成了AOP署理
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 需要署理的话,在这里完成的署理
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

4、wrapIfNecessary方式执行

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

    // 在postProcessBeforeInstantiation方式中可能已经完成过署理了
    // 若是已经完成署理了,那么直接返回这个署理的工具
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }

    // 在postProcessBeforeInstantiation方式中可能已经将其符号为不需要署理了
    // 这种情况下,也直接返回这个Bean
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }

    // 跟在postProcessBeforeInstantiation方式中的逻辑一样
    // 若是不需要署理,直接返回,同时在advisedBeans中符号成false
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取可以应用到这个Bean上的通知
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 若是存在通知的话,说明需要被署理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 到这里建立署理,现实上底层就是new了一个ProxyFactory来建立署理的
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
 // 若是没有通知的话,也将这个Bean符号为不需要署理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

关于建立署理的详细源码剖析,在Spring中AOP相关的API及源码剖析,原来AOP是这样子的一文中已经做了详细先容,以是本文不再赘述,现在我们的重点将放在Spring是若何剖析出来通知的,对应方式就是getAdvicesAndAdvisorsForBean,其源码如下:

第一步:挪用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

   // 通过findEligibleAdvisors方式返回对应的通知
   // 这个方式会返回所有能应用在指定的Bean上的通知
   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);

   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}

第二步:挪用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取到所有的通知
    List<Advisor> candidateAdvisors = finDCandidateAdvisors();
    // 从获取到的通知中筛选出能应用到这个Bean上的通知
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

第三步:挪用org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors获取到所有的通知

// 这个方式的目的就是为了获取到所有的通知
protected List<Advisor> findCandidateAdvisors() {

    // 先挪用父类的方式,父类会去查找容器中所有属于Advisor类型的Bean
    List<Advisor> advisors = super.findCandidateAdvisors();

   // 这个类自己会通过一个aspectJAdvisorsBuilder来构建通知
    // 构建的逻辑就是剖析@Aspect注解所标注的类中的方式
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }

    // 最后返回这些通知
    return advisors;
}

第四步:org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#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<>();
     // 会获取到容器中的所有BeanName
     String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
       this.beanFactory, Object.class, true, false);
     for (String beanName : beanNames) {
      // 若是对beanName设置了正则匹配的话,那么要凭据正则表达式的匹配规则举行过滤
      // 默认是没有的,可以以为isEligibleBean始终返回true
      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;
      }
      // 判断类上是否添加了@Aspect注解
      if (this.advisorFactory.isAspect(beanType)) {
       aspectNames.add(beanName);
       AspectMetadata amd = new AspectMetadata(beanType, beanName);
       // 默认就是SINGLETON,署理切面工具是单例的
       if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // 最后从这个切面实例中剖析出所有的通知
                            // 关于通知剖析的详细代码就不再剖析了
         MetadataAwareAspectInstanceFactory factory =
          new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
        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);
       }
  // 省略部门代码
  return advisors;
 }

第五步:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

protected List<Advisor> findAdvisorsThatCanApply(
    List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

这个方式实在没啥好剖析的,就是凭据前面找出来的Advisor聚集举行遍历,然后凭据每个Advisor对应的切点来举行匹配,若何合适就返回,对应源码也对照简单,固然条件是你看过我之前那篇AOP源码剖析的文章了.

总结

这篇文章对照短,由于没有做很细节的源码剖析,对照详细的源码剖析已经放到上篇文章中了。最后我这里画个流程图总结一下AOP是怎么被应用到Bean的生命周期中的

Spring源码的最后一点弥补

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    // 1.实例化    ---> createBeanInstance
    // 2.属性注入  ---> populateBean
    // 3.初始化    ---> 完成初始化及AOP
    // exposedObject 就是完成初始化后的Bean  
    // 省略部门代码,省略代码的作用已经在上面标明晰

    // 下面的代码现实上主要目的在于处置循环依赖
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // 我们之前早期露出出去的Bean跟现在最后要放到容器中的Bean不是同一个
            // allowRawInjectionDespiteWrapping为false
            // 而且当前Bean被当成依赖注入到了其余Bean中
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 获取到当前Bean所隶属的Bean
                String[] dependentBeans = getDependentBeans(beanName);
                // 要获得真实的隶属的Bean
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    // 移除那些仅仅为了类型检查而建立出来
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
     // 抛出异常
                    // 泛起了循环依赖,而且现实存在容器中的Bean跟被看成依赖注入到其余Bean中的
                    // 不是同一个工具,这个时刻也报错
                }
            }
        }
    }

    // 注册bean的销毁回调
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

现实这段代码照样跟循环依赖相关,关于循环依赖的文章,人人可以参考:面试必杀技,讲一讲Spring中的循环依赖

若是我的文章能帮到你,记得点个赞哈~!

我叫DMZ,一个在学习路上匍匐前行的小菜鸟!

程序员DMZ
点赞、转发、在看,多谢多谢!
喜欢作者