Spring 中 createBeanInstance详解

456 阅读3分钟

「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

1.前言

createBeanInstance 在spring 容器初始化时,通常是在

org.springframework.context.support.AbstractApplicationContext#refresh --》 org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization --》 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons --》 org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String) --》 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]) --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance 通常的调用路径是上面的,这里大家有感兴趣的,可以自行点进去查看。

这里这个方法的主要作用就是:使用适当的实例化策略为指定bean创建新实例:工厂方法,构造函数自动装配,或简单实例化

2.createBeanInstance 源码

createBeanInstance.jpg

2.1 获取bean 类型,判断bean 是否能被创建

mbd: 记录bean定义信息的对象,这里在前面文章4.1章节讲过 resolveBeanClass: 解析指定的beanName 并返回对应的 class 类型,前面文章2.1章节讲过 当 beanClass != null && 当前类的修饰符不是public && 不允许访问非公共的构造方法,则抛出异常

2.2 使用回调或工厂方法创建

  1. 获取bean 的 Supplier 对象,如果他不为null,则使用它的回调方法,来创建bean

1. obtainFromSupplier : 从给定的 Supplier 中获取bean 实例,(即前面说的回调方法)

图片.png - Supplier:提供式函数接口,这里面spring 设计思想是,当可以直接创建bean 实例,不通过工厂创建,又或者后面使用构造方法创建,会使用反射创建对象,那样会比较耗费性能。 - 这个方法中首先 从 Supplier 中获取 instance,然后 通过instance 创建 BeanWrapper 对象,初始化BeanWraper 然后返回该对象。

  1. 获取它的工厂方法,如果工厂方法不为null,则会使用这个工厂方法来创建bean实例,并返回 这里 instantiateUsingFactoryMethod(beanName, mbd, args):使用指定的工厂方法实例化该 bean,这个方法后面有时间的话,在细讲

2.3 使用构造方法创建

  • resolved 表示构造函数是否已经解析完成
  • autowireNecessary 表示是否需要自动装配 这里需要先提一下,一个类可能会有多个构造方法,参数类型各不相同,所以spring 会根据参数的个数和类型,寻找对应的构造方法
  • 首先加把锁保证同时间,只有一个线程在创建。
  • resolvedConstructorOrFactoryMethod:包可见字段,用于缓存已解析的构造函数或工厂方法,当它不为null时,表示构造函数已解析完成。
  • 当它解析完成后
    • 判断是否需要自动装配,如果需要的话,就返回构造函数自动注入,否则的话就使用默认的构造器

    • autowireConstructor(beanName, mbd, ctors, args):构造函数自动注入

    • instantiateBean(beanName, mbd):默认构造器

2.4 bena 初次 加载

  • 到这一步,说明 bean 是第一次加载,所以没有对构造函数进行相关缓存(resolved 为 false),调用 determineConstructorsFromBeanPostProcessors 方法来获取指定的构造函数列表。

    1.determineConstructorsFromBeanPostProcessors

    图片.png

    • 判断当beanClass 不为null 时,且 已注册实例化的WareBeanPostProcessor
    • 取出所有的 beanPostProcessors,遍历
    • 当 bp 是 SmartInstantiationAwareBeanPostProcessor 类型时,调用 determineCandidateConstructors 方法,获取当前bean 的构造方法,当它不为 null 时返回。
  • 当 解析的构造函数不为空 || 注入类型为构造函数自动注入 || bean定义中有构造器参数 || 传入参数不为空 接着调用 autowireConstructor(beanName, mbd, ctors, args) 方法

2.5 获取最优构造函数

getPreferredConstructors : 获取最优构造函数,这里在 org.springframework.beans.factory.support.RootBeanDefinition#getPreferredConstructors 默认实现为null

  • 当 getPreferredConstructors 不为 null 时,直接调用 autowireConstructor(beanName, mbd, ctors,null)

2.6 返回默认构造函数

这里说明上面都未成功返回,就只能执行默认的构造函数了。

3.总结

createBeanInstance总结.jpg