Spring 源码阅读笔记 (八) 支线 createBean 方法解读

283 阅读10分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

Spring 源码阅读笔记(八)

前篇导航

Spring 源码阅读笔记(一)
Spring 源码阅读笔记(二)
Spring 源码阅读笔记(三)
Spring 源码阅读笔记(四)
Spring 源码阅读笔记(五)
Spring 源码阅读笔记(六) 主线 registerBeanPostProcessors解读
Spring 源码阅读笔记(七) 支线 getBean方法解读

前篇回顾

在上一章节中,把getBean方法的整个流程走了一遍,可以得到一个信息,调用AbstractBeanFactory的getBean方法时,如果工厂中找不到类的话,不会返回空,而是会调用CreateBean方法。那么这篇文章解读的就是createBean方法。

正式开始

关于CreateBean,这个方法具体的实现代码位于AbstractAutowrieCapableBeanFactory中。首先先关注一下这个方法的入参。

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args);
  1. String beanName 要创建的Bean名称
  2. RootBeanDefinition mbd 要创建的Bean的定义信息
  3. Object[] args 不出意外这里传空

首先呢,读方法之前,粗略的看一下重点,在哪里,哪些细节要抠。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // 确保此时实际解析了 bean 类,
   // 并克隆 bean 定义以防动态解析的 Class 
   // 无法存储在共享的合并 bean 定义中。
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // 准备方法覆盖。
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      // .....
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 让 BeanPostProcessors 有机会返回一个代理而不是目标 bean 实例。
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
   // ...
   }

   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // ....
   }
   catch (Throwable ex) {
      // ....
   }
}

上方的代码粗略看一眼,完成了以下的几个点。

  1. 新创建了一个BeanDefinition对象
  2. 解析上层传过来BeanDefintion,解析出Class信息,赋值给了新的BeanDefinition
  3. 调用resolveBeforeInstantiation,注释解释让BeanPostProcessors有机会返回代理,而不是目标bean实例。
  4. Object beanInstance = doCreateBean(beanName, mbdToUse, args);

从这里基本都可以看出,具体关键性的代码是resolveBeforeInstantiation方法和doCreateBean。

resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      // 确保bean类在这一点上得到了解决。
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
          // .....
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

该方法一进入便可看到一个判断,beforeInstantiationResolved这个值是做什么的,要看一下他的注释。解释如下

  • Package-visible field that indicates a before-instantiation post-processor having kicked in.
  • Package visible字段,指示前实例化后处理器已启动。 讲真话,我看不懂是什么意思😂,知道这里是null值就行,因为我们并没有设置他的值。
    那么这里false.equals(null) = false 在加上一个取反,很明显if进来了。

接下来进入第二个if判断,BeanDefinition中的synthetic属性为boolean类型,默认为false,他这里取反了一下,这个条件也成立,但是看到他有个&&,这里要去看一下他的代码。

protected boolean hasInstantiationAwareBeanPostProcessors() {
   return !getBeanPostProcessorCache().instantiationAware.isEmpty();
}

class AbstractBeanFactory:
BeanPostProcessorCache getBeanPostProcessorCache() {
   BeanPostProcessorCache bppCache = this.beanPostProcessorCache;
   if (bppCache == null) {
      bppCache = new BeanPostProcessorCache();
      for (BeanPostProcessor bpp : this.beanPostProcessors) {
         if (bpp instanceof InstantiationAwareBeanPostProcessor instantiationAwareBpp) {
            bppCache.instantiationAware.add(instantiationAwareBpp);
            if (bpp instanceof SmartInstantiationAwareBeanPostProcessor smartInstantiationAwareBpp) {
               bppCache.smartInstantiationAware.add(smartInstantiationAwareBpp);
            }
         }
         if (bpp instanceof DestructionAwareBeanPostProcessor destructionAwareBpp) {
            bppCache.destructionAware.add(destructionAwareBpp);
         }
         if (bpp instanceof MergedBeanDefinitionPostProcessor mergedBeanDefBpp) {
            bppCache.mergedDefinition.add(mergedBeanDefBpp);
         }
      }
      this.beanPostProcessorCache = bppCache;
   }
   return bppCache;
}

看到这里有点懵了,方法的含义是获取Bean后处理的缓存。然后这个beanPostProcessorCache属性我不记得什么时候设置过了,这里打个断点看一下吧。

image.png

这里有个应用事件监听器,我有点印象,虽然不知道是干嘛的,我印象中他是在invokeBeanFactoryPostProcessors方法时创建的。那么由此也得知了hasInstantiationAwareBeanPostProcessors方法返回为False,后面的代码块也就不执行了。 这个方法返回的是null值。

后续进入doCreateBean方法。

doCreateBean方法

doCreateBean 入参

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

这个方法一共只有三个入参,很透明。

  1. beanName 需要创建的Bean的名称
  2. BeanDefintiton Bean定义信息,在上一步已经把ClassName转换成BeanClass
  3. args 从getBean方法传过来的,不出意外的话,这个是为空。

后面由于这个方法体比较长,这里还是采用分段阅读方法,具体分段规则是根据源码中的注释来分段的。

doCreateBean 第一段代码

// Instantiate the bean.
// 实例化 bean。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
   instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
   mbd.resolvedTargetType = beanType;
}

接下来看第一段代码,根据代码上方的注释可以看到,实例化Bean,那么众所周知,创建一个对象要分几步,实例化,初始化。在实例化时只是创建了一个对象,这里粗略扫一眼可以看到几个比较关键的方法。

  1. createBeanInstance
    • 返回一个BeanWrapper,根据字面意思就是Bean包装器,我还没有看里面的代码,我先简单理解成对Class的一个封装。
  2. getWrappedInstance
    • 字面意思是获取包装器实例,现在没看代码,我的理解是通过Class,instance出来一个对象。

接下来看看这两个方法的代码具体如何实现

createBeanInstance

完整的createBeanInstance方法也蛮长的,这里分段吧,方便讲解。

// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);

// .... 中间省略一些不会进入的if
   
// Shortcut when re-creating the same bean...
// 重新创建同一个bean时的快捷方式...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
   synchronized (mbd.constructorArgumentLock) {
      if (mbd.resolvedConstructorOrFactoryMethod != null) {
         resolved = true;
         autowireNecessary = mbd.constructorArgumentsResolved;
      }
   }
}
if (resolved) {
   if (autowireNecessary) {
      return autowireConstructor(beanName, mbd, null, null);
   }
   else {
      return instantiateBean(beanName, mbd);
   }
}

这里的方法很明显了,一进入第一行就是获取当前要创建Bean的Class。

后来进入一个If判断,args正常情况下势必为null。进入If。
不出意外的话,BeanDefinition中的resolvedConstructorOrFactoryMethod属性我们并没有设置过,所以为null,这里不会进入。由于这个if没有进入,所以resolved的值没有发生改变,那么下一个if也不会进入。

// Candidate constructors for autowiring?
// 自动装配的候选构造函数?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
      mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
   return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
// 默认构造的首选构造函数?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
   return autowireConstructor(beanName, mbd, ctors, null);
}

这段代码粗略读下来,获取的类的构造方法,判断构造方法有没有自动注入,有的话,走使用构造方法构建实例的方法。

// No special handling: simply use no-arg constructor.
// 没有特殊处理:只需使用无参数构造函数。
return instantiateBean(beanName, mbd);

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
   try {
      Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

image.png

image.png

这里代码一层一层追下来,可以得知,他是通过反射来创建了一个实例。

然后把实例封装进了BeanWrapper类中,这个类是干什么的不重要,只要记住,可以通过这个对象拿到实例就可以了。

doCreateBean 第二段代码

// Allow post-processors to modify the merged bean definition.
// 允许后处理器修改合并的 bean 定义。
synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
      try {
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      catch (Throwable ex) {
          throw .....
      }
      mbd.postProcessed = true;
   }
}

postProcessed默认值为false,由于我们没有进行过更改,所以这里会进入If。

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
   for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
      processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
   }
}

这里扫一眼就行,没什么实质意义,系统定义了几个PostProcessor这里要执行一下。

随后mbd.postProcessed = true;设置的postProcessed状态,代表已经执行过了。

doCreateBean 第三段代码

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 急切地缓存单例以便能够解析循环引用
// 即使由生命周期接口(如 BeanFactoryAware)触发。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
      isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
      logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

方法一开始拿到了一个bool类型的值earlySingletonExposure,这里取了三个值。

  1. 是否单例
  2. 是否允许循环引用 默认为true
  3. 判断当前创建的Bean在整个工厂中是否正在创建,有点拗口。这里是为true的,因为我们现在正在创建的就是这个类。

然后后面就是添加了个,单例工厂,我猜测这个工厂的作用就是把刚刚上面实例化的Bean对象,给返回出去,来解决循环依赖问题。

doCreateBean 第四段代码

// Initialize the bean instance.
Object exposedObject = bean;
try {
   populateBean(beanName, mbd, instanceWrapper);
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
   if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
      throw (BeanCreationException) ex;
   }
   else {
      throw ......
   }
}

这里可能比较疑惑,为什么要把Bean重新赋值,这里可以想一下,Bean是Object,也就是引用类型,那么在刚刚的代码中,有把Bean赋值给刚刚解决循环引用的地方,所以这里为了在那个方法被调用时Bean不发生改变,所以这里重新声明了一个对象。

后面为这个对象进行populate操作,也就是填充属性。

populateBean
populateBean 入参
  1. String beanName
  2. RootBeanDefinition mbd
  3. @Nullable BeanWrapper bw 封装着Bean的实例对象
populateBean 第一段代码
if (bw == null) {
   if (mbd.hasPropertyValues()) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
   }
   else {
      // Skip property population phase for null instance.
      return;
   }
}

bw不为空,具体看入参

populateBean 第二段代码
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
   MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
   // Add property values based on autowire by name if applicable.
   if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
      autowireByName(beanName, mbd, bw, newPvs);
   }
   // Add property values based on autowire by type if applicable.
   if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      autowireByType(beanName, mbd, bw, newPvs);
   }
   pvs = newPvs;
}

由于我们这个里面没有设置properties文件,所以pvs刚开始时是为null的。

第二个变量的自动装配模式,由于我们没有另外的设置,所以采用的是默认方式,也就是注解注入的方式,下面这里的if中,分别也byName或者byType,他们的所代表的也就是setter方法的注入方式。有兴趣可以去读一下,我这里就跳过了。因为我们在正常的开发中,通常是不设置这个的,都是通过注解注入。

initializeBean
initializeBean 第一段代码
invokeAwareMethods(beanName, bean);

private void invokeAwareMethods(String beanName, Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ClassLoader bcl = getBeanClassLoader();
         if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
         }
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

在方法一开始执行了aware接口的方法。但是这里发现一个细节,并没有发现applicationAware接口。接着往下看。

initializeBean 第二段方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
   // 执行BeanPostProcessor
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

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

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

从上方的代码可以看出来获取了所有的BeanPostProcessor,然后遍历一遍去执行他们的Before方法。

这里值得一提的是。ApplicationContextAwrea是在PostProcessor里面处理的。 image.png

initializeBean 第三段方法
try {
   // 执行Bean的初始化方法,afterProperties方法也是在这里执行的。
   // Xml中指定的init-methods。
   invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
   throw new BeanCreationException(
         (mbd != null ? mbd.getResourceDescription() : null),
         beanName, "Invocation of init method failed", ex);
}

这里就没有什么好读的了。调用了一下xml里面的init方法。

image.png 值得一提的是,InitializingBean接口中的afterPropertiesSet方法也是在这个时候被执行的。

initializeBean 第四段方法
if (mbd == null || !mbd.isSynthetic()) {
   // 执行BeanProcessor的后置增强器。
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

这里就简单,和前面一样BeanPostProcess方法一样。只不过有befor方法换成了after方法。

doCreateBean 第五段代码

if (earlySingletonExposure) {
   Object earlySingletonReference = getSingleton(beanName, false);
   if (earlySingletonReference != null) {
      if (exposedObject == bean) {
         exposedObject = earlySingletonReference;
      }
      else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
         String[] dependentBeans = getDependentBeans(beanName);
         Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
         for (String dependentBean : dependentBeans) {
            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
               actualDependentBeans.add(dependentBean);
            }
         }
         if (!actualDependentBeans.isEmpty()) {
            throw .....
         }
      }
   }
}

由于上方的boolean对象没有变过,所以此时他还是为True。第一行代码获取了一个他的单例工厂中的对象。

image.png 由于allowEarlyReference是为false的。所以获取的对对象是个null,那么也就代表剩余的If不会进入。

doCreateBean 第六段代码

// Register bean as disposable.
// 将 bean 注册为一次性的。
try {
   registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
   throw new BeanCreationException(
         mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;

后面直接放回了上面代码中经历了种种操作的Bean。至于registerDisposableBeanIfNecessary这个方法,没看懂他的实现,并且经过debug后,发现他里面的代码并没有执行,所以这里先跳过吧。

告一段落

这篇文章到这里就结束了,相信看完这篇文章后,如果面试时,对方问道Bean的创建流程时你就可以对答如流了。大家加油~

都看到这了,点个赞再走呗,宝~

结束语

写文章的目的是为了帮助自己巩固知识,写的不好或者错误的地方可以在评论区指出。如果您看了文章觉得对您有所帮助可以点个赞,如果发现有些问题产生了疑惑,或者不明白的可以评论、加我微信,一定知无不言。当然也希望和大家交个朋友,相互学习。