天天看点

【IoC-3】Spring bean 的创建过程前言正文补充:bean 创建的完整过程小结

bean 的创建过程

  • 前言
  • 正文
  • 补充:bean 创建的完整过程
  • 小结

系列博文:

【IoC-0】SpringIoC引入

【IoC-1】IoC之控制反转引入

【IoC-2】IoC之BeanDefinition扫描注册

【IoC-3】Spring bean 的创建过程

【IoC-4】IoC之依赖注入原理

相关阅读:

@Resource与@Autowired的区别

前言

Spring 提供了"控制反转"的能力,也就是将 bean 的创建交由 Spring 去统一处理。

前文分析了要实现"控制反转"的功能,Spring 需要解决的问题是:

  1. BeanDefinition 的扫描和注册
  2. 根据 BeanDefinition 来创建 bean 的实例

可以说"BeanDefinition 的扫描和注册"只是前戏,bean 实例的创建才是主菜。

上一篇已经分析了 BeanDefinition 的扫描和注册,这里我们主要再分析一下 bean 实例的创建过程。

正文

一个普通的单例 bean,如果没有特殊的指定 FactoryMethod 或者 constructor 的话,就会使用默认的构造函数来创建 bean 的实例。

那么,我们可以为一个普通的单例 bean 添加一个默认的构造函数,然后在上面打上断点,来观察 bean 实例创建时的调用堆栈。

观察调用堆栈,是阅读源码的一个小技巧。可以快速的观察到程序从开始到断点处经过了哪些处理过程。
【IoC-3】Spring 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 isn't 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 完整的创建过程:

【IoC-3】Spring bean 的创建过程前言正文补充: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)

如果本文对你有所帮助,欢迎点赞收藏!