老王读Spring IoC-3Spring bean 的创建过程

但使书种多,会有岁稔时。这篇文章主要讲述老王读Spring IoC-3Spring bean 的创建过程相关的知识,希望能为你提供帮助。
@[TOC](bean 的创建过程)
前言Spring 提供了" 控制反转" 的能力,也就是将 bean 的创建交由 Spring 去统一处理。
前文分析了要实现" 控制反转" 的功能,Spring 需要解决的问题是:

  1. BeanDefinition 的扫描和注册
  2. 根据 BeanDefinition 来创建 bean 的实例
可以说" BeanDefinition 的扫描和注册" 只是前戏,bean 实例的创建才是主菜。
上一篇已经分析了 BeanDefinition 的扫描和注册,这里我们主要再分析一下 bean 实例的创建过程。
版本约定Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)
正文【老王读Spring IoC-3Spring bean 的创建过程】一个普通的单例 bean,如果没有特殊的指定 FactoryMethod 或者 constructor 的话,就会使用默认的构造函数来创建 bean 的实例。
那么,我们可以为一个普通的单例 bean 添加一个默认的构造函数,然后在上面打上断点,来观察 bean 实例创建时的调用堆栈。
从调用堆栈中,可以看到,bean 实例的创建是在执行 AbstractApplicationContext#finishBeanFactoryInitialization() 的时候,调用 AbstractBeanFactory#getBean() 触发的。
最终会调用 AbstractAutowireCapableBeanFactory#createBeanInstance():
/** * 通过一定的实例化策略,为指定的 bean 创建一个新的实例。 * 实例化策略为:FactoryMethod --> constructor autowiring(构造注入) --> simple instantiation(调用默认构造函数) * Create a new instance for the specified bean, using an appropriate instantiation strategy: factory method, constructor autowiring, or simple instantiation. */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class< ?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null & & !Modifier.isPublic(beanClass.getModifiers()) & & !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isnt public, and non-public access not allowed: " + beanClass.getName()); }Supplier< ?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); }// 1. 通过指定的 FactoryMethod 来创建 bean 的实例 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); }// Shortcut when re-creating the same 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); } }// 2. 构造注入 // 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); }// 3. 使用无参构造函数来创建 bean 的实例。(即默认的构造函数) // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }

补充:bean 创建的完整过程createBeanInstance() 方法只是将 bean 的实例创建出来了,它还不是一个完整的 bean,因为 bean 里面依赖的属性还没有填充值。
AbstractAutowireCapableBeanFactory.doCreateBean() 的源码可以看到 bean 完整的创建过程:
老王读Spring IoC-3Spring bean 的创建过程

文章图片

小结bean 实例的创建是在执行 AbstractApplicationContext#finishBeanFactoryInitialization() 的时候,调用 AbstractBeanFactory#getBean() 触发的。
最终是由 AbstractAutowireCapableBeanFactory#createBeanInstance() 方法来完成 bean 实例的创建的。
bean 实例的创建策略为(优先级级从前往后):
  1. 通过指定的 FactoryMethod 来创建
  2. 构造注入的方式(通过指定的构造函数)
  3. 通过默认的构造函数来创建
创建一个完整的 bean 分三个阶段:
  1. AbstractAutowireCapableBeanFactory#createBeanInstance()
    创建 bean 的实例
  2. AbstractAutowireCapableBeanFactory#populateBean()
    填充 bean 的依赖
  3. AbstractAutowireCapableBeanFactory#initializeBean()
    初始化 bean。
    对 bean 的实例执行一些初始化方法:
    awareMethods --> BeanPostProcessor --> initMethod(InitializingBean#afterPropertiesSet、指定的 initMethod)
如果本文对你有所帮助,欢迎点赞收藏!
有关 Spring 源码方面的问题欢迎一起交流,备注:51cto (vx: Kevin-Wang001)

    推荐阅读