Spring IOC:CreateBean环节中的流程转换

一 . 前言

此篇文章的目的 :

  • 梳理Bean 的创建流程 , 便于后续查找问题点
  • 梳理过程中的参数情况 , 减少Debug的需求
  • 梳理整体家族体系

Bean 创建的几个触发场景 :

  • BeanFactory 的 #getBean(...) 方法来请求某个实例对象的时候
  • 使用 ApplicationContext 容器时 , 会在启动时立即注册部分 Bean

二 . 流程梳理

先来看一个很常见的图 , 来源于 @ topjava.cn/article/139…

同样的 , 这篇的流程整理也是按照此流程 , 先看一下整个流程大纲

> 实例化过程
    1 实例化Bean 对象 : Spring 容器根据实例化策略对 Bean 进行实例化
        ?- 常用策略模式 , 通常包括反射和 CGLIB 动态字节码
            - SimpleInstantiationStrategy : 反射
            - CglibSubclassingInstantiationStrategy : 通过 CGLIB 的动态字节码 (默认)
    	- createBeanInstance(...) 方法实现 ,返回 BeanWrapper
            - BeanWrapper  : 低级 Bean 基础结构的核心接口
            ?- 低级 Bean : 无任何属性
    	- BeanWrapperImpl 对  Bean 进行“包裹” ,用于注入Bean 属性
    	|- InstantiationStrategy -> SimpleInstantiationStrategy
    	|- SimpleInstantiationStrategy -> CglibSubclassingInstantiationStrategy
    2 注入对象属性
        |- 实例化完成后,如果该 bean 设置了一些属性的话,则利用 set 方法设置一些属性
    3 检测 , 激活 Aware
    	| -感知 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    	|- 如果该 Bean 实现了 BeanNameAware 接口
            |- 则调用 #setBeanName(String beanName) 方法
    4 BeanPostProcessor 前置处理
        |- 如果该 bean 实现了 BeanClassLoaderAware 接口
            |- 则调用 setBeanClassLoader(ClassLoader classLoader) 方法。
        |- 如果该 bean 实现了 BeanFactoryAware接口
            |- 则调用 setBeanFactory(BeanFactory beanFactory) 方法
        |- 如果该容器注册了 BeanPostProcessor
            |- 则会调用#postProcessBeforeInitialization
            |- 完成 bean 前置处理
    5 检查 InitializingBean 和 init-method
        |- 如果该 bean 实现了 InitializingBean 接口
            |-则调用#afterPropertiesSet() 方法
        |- 如果该 bean 配置了 init-method 方法,则调用其指定的方法。
    6 BeanPostProcessor 后置处理
        |- 初始化完成后,如果该容器注册了 BeanPostProcessor
            |- 则会调用 #postProcessAfterInitialization,完成 bean 的后置处理。
    7 注册必要的Destruction 回调
    8 使用Bean
        |- 对象完成初始化,开始方法调用
    9 检查 DisposableBean 和 destory-method
    	|- 在容器进行关闭之前,如果该 bean 实现了 DisposableBean 接口
            |- 则调用 #destroy() 方法
            |- 在容器进行关闭之前,如果该 bean 配置了 destroy-method 
            |- 则调用其指定的方法。

2.1 实例化创建

引言 : 谁调用的 ?

doGetBean 会有2种调用途径 :

一种是 ApplicationContext 加载的时候 , 会初始化当前容器需要的 Bean :

  • C- SpringApplication # run
  • C- SpringApplication # prepareContext
  • C- SpringApplication # applyInitializers : 调用 ApplicationContextInitializer 集合 , 分别执行对应的 initialize
  • C- ApplicationContextInitializer # initialize
  • C- ConditionEvaluationReport # get
  • C- AbstractBeanFactory # getBean

第二种是容器必要 Bean 加载完成后 ,refresh 时处理所有的 Bean

  • C- SpringApplication # run
  • C- SpringApplication # refreshContext
  • C- AbstractApplicationContext # refresh()
    • 此处refresh 中有多处会调用 getBean
    • C- AbstractApplicationContext # invokeBeanFactoryPostProcessors
    • C- AbstractApplicationContext # registerBeanPostProcessors
    • C- AbstractApplicationContext # onRefresh();
    • C- AbstractApplicationContext # finishBeanFactoryInitialization
  • C- AbstractBeanFactory # getBean

PS : 另外还有一种就是因为依赖关系被递归调用的

2.1.1 doGetBean 入口

C171- AbstractBeanFactory
	M171_01- getBean(String name, Class<T> requiredType)
            ?- 直接调用 doGetBean , 这里会根据类型不同调用不同的 getBean

doGetBean 可以分为 5 个阶段

  • 阶段一 : 生成 beanName 后尝试从单例缓存中获取
  • 阶段二 : 单例缓存中获取失败后 ,尝试 ParentBeanFactory 中获取
  • 阶段三 : 依赖检查 , 保证初始化当前bean所依赖的bean
  • 阶段四 : 三种不同的类型获得 Bean 实例 (Singleton / prototype / other)
  • 阶段五 : 此时 Bean 已经准备完成了 , 此处检查所需的类型是否与实际bean实例的类型匹配 , 不符需要转换
// 核心方法一 :
M171_02- doGetBean( String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)

    // 阶段一 : 生成 beanName 后尝试从单例缓存中获取
    1- transformedBeanName 生成 beanName -> PS:M171_02_01
    2- getSingleton(beanName) : 单例方式获取一个 Bean , 循环依赖就是这个环节处理 -> -> PS:M171_02_02
    IF- sharedInstance != null : 如果此时已经生成 , 且 args 为空不需要继续加载
        - getObjectForBeanInstance(sharedInstance, name, beanName, null) 

    // 阶段二 : 单例缓存中获取失败后 ,尝试 ParentBeanFactory 中获取
    ELSE-
        3- isPrototypeCurrentlyInCreation(beanName) : 如果是原型模式且存在循环依赖则抛出异常
        4- getParentBeanFactory() : 检查这个工厂中是否存在bean定义
            ?- 如果工厂中已经存在了 , 会有四种情况会直接 return -> PS:M171_02_03
            4.1- AbstractBeanFactory :  parentBeanFactory.doGetBean
            4.2- args != null : parentBeanFactory.getBean(nameToLookup, args)
            4.3- requiredType != null: parentBeanFactory.getBean(nameToLookup, requiredType)
            4.4- 都不符合 : parentBeanFactory.getBean(nameToLookup)
        - 如果为类型检查而获取实例,而不是实际使用 , 则将指定的bean标记为已经创建 -> PS:M171_02_04
        - RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName) + checkMergedBeanDefinition
            ?- RootBeanDefinition的获取和检查  LV171_001

        // 阶段三 : 依赖检查 , 保证初始化当前bean所依赖的bean
        -  对于属性 LV171_001:mbd , 通过 getDependsOn 获取所有依赖
        FOR- 循环所有的依赖 , 分别调用 registerDependentBean + getBean 进行递归操作

        // 阶段四 : 三种不同的类型获得 Bean 实例
        5- 判断 Bean 的类型不同创建 Bean -> PS:M171_02_05
            5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
            5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
            5.3- 其他 : 主要是通过 Scope 控制域 + Prototype 流程

        // 阶段五 : 此时 Bean 已经准备完成了 , 此处检查所需的类型是否与实际bean实例的类型匹配
        IF- 如果实例不匹配 , 则需要转换, 转换后直接返回
            - return getTypeConverter().convertIfNecessary(bean, requiredType)
        // 如果上面没有返回 , 则直接发返回原本的Bean 

// 其他方法
M171_10- getSingleton(String beanName, ObjectFactory<?> singletonFactory) : 获取单例 Bean
M171_20- getObject() : 这里实际是调用 FactoryBean
    ?- 这里会通过一个 方法回调的语法糖 , 调用 createBean , 整个就连起来了 -> M173_02

// 核心方法二 : 实例化 Bean
// 首先要知道 , 前面传过来的是什么 : TODO
M171_ - getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)

// PS : doGetBean 在附录中展示

2.1.2 doGetBean 补充节点

PS:M171_02_01 获取 beanName

--> canonicalName(BeanFactoryUtils.transformedBeanName(name))
---->
C181- SimpleAliasRegistry
    F181_01- Map<String, String> aliasMap
    M- canonicalName(BeanFactoryUtils.transformedBeanName(name))
        - 主要是从 F181_01 中获取 alias 别名
            ?- PS : 这里的代码有点意思 , 看样子是为了解决别名链的问题 , 即别名对应的还有别名 , 直到取不出来

public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    do {

        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    // 循环获取别名对应的是否存在别名 , 直到获取不到
    }while (resolvedName != null);
    return canonicalName;
}

PS:M171_02_03 为什么四种情况会直接返回 ?

4.1- AbstractBeanFactory :  parentBeanFactory.doGetBean
4.2- args != null : parentBeanFactory.getBean(nameToLookup, args)
    ?- 使用显式参数委托给父类
4.3- requiredType != null: parentBeanFactory.getBean(nameToLookup, requiredType)
    ?- 委托给标准的getBean方法
4.4- 都不符合 : parentBeanFactory.getBean(nameToLookup)
    ?- Pro2

// 这里直接返回是因为存在父 BeanFactory , 且存在 BeanDefinition , 这就意味着ParentBeanFactory 能处理 , 基于 Pro 1 的原因 , 选择直接返回 

// Pro 1 :  为什么从父工厂里面获取 -> BeanFactory parentBeanFactory = getParentBeanFactory();
这是一个递归操作 , 也是仿照双亲委派的方式来处理 , 即先有父对象来加载对应的对象

同样的 , 当进入 doGet 的时候 , 默认通过父方法去加载 , 如果父方法处理完成了 , 即加载出 Bean 了 , 就直接返回
好处呢 , 想了一下 , 可以保证每个实现能专注于其本身需要处理的 Bean , 而不需要关注原本就会加载的 Bean
回顾一下双亲委派的目的 : 避免重复加载 + 避免核心类篡改    

// Pro 2 : 四种方式去返回的区别
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

PS:M171_02_04 对于只检查的那样处理有什么目的 ?


这里如果是只检查而无需创建 , 会在 markBeanAsCreated 方法中做2件事
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);    

这样的目的是为了即标注方法已经检查成功 , 而避免走没必要的反复流程 ,允许bean工厂为重复创建指定bean而优化其缓存
--> 实际逻辑    

// Step 1 : alreadyCreated 是什么 ?
Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
    ?- alreadyCreated 包含 至少已经创建过一次的bean的名称的 Set 集合

// Step 2 : 如何利用这个对象 ?
1 : AbstractAutowireCapableBeanFactory # getTypeForFactoryBean
    ?- 这里会通过这个对象校验引用的工厂bean还不存在,那么在这里退出——不会仅仅为了获取FactoryBean的对象类型而强制创建另一个bean

2 : clearMetadata 时 , 需要判断是否为空

PS:M171_02_05 三种不同方式的本质区别 ?

相同点 :  最终调用 getObjectForBeanInstance
5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
    - 首先通过 getSingleton 方法, 保证加载的唯一性
    - 回调 createBean 创建 Bean
    - 通过 getObjectForBeanInstance 实例化真正的 Bean

5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
    - 仔细看就能发现 , 没有相关的 scope 对象控制 , 直接进行创建

5.3- 其他 : 主要是通过 Scope 控制域 + Prototype 流程
    - 它是 singleton 的结合体 ,
    - 首先会准备一个 Scope 对象用于控制 Scope 域内的 Bean 情况
    - 再调用和 Prototype 一致的流程进行创建

PS:M171_02_06 sharedInstance 和 bean 的区别

这里可以看到 , 首先通过 createBean 创建了一个 Object 对象 sharedInstance , 又通过 getObjectForBeanInstance 生成了一个 Bean ,他们有什么本质的区别 ?

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

// 这就涉及到 Bean 的工厂了 , 一般情况下 , createBean 创建的 Bean 就是一个 完整的 Bean
// 但是 ,如果它是一个FactoryBean,需要使用它来创建一个bean实例,除非调用者实际上想要一个对工厂的引用。

sharedInstance 中的 Bean 是已经走完 Bean 创建流程的 Bean了

2.1.3 AbstractBeanFactory # createBean

C171- AbstractBeanFactory
	M171_03- createBean(String beanName, RootBeanDefinition mbd, Object[] args) 
            P- mbd :  BeanDefinition 对象 , 已经合并了父类属性
            p- args : 用于构造函数或者工厂方法创建 Bean 实例对象的参数

2.1.4 AbstractAutowireCapableBeanFactory # createBean 主流程

C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
    M173_02- createBean(String beanName, RootBeanDefinition mbd,Object[] args)
        ?- M170_01 方法的默认实现
        LV173_02_01- RootBeanDefinition mbdToUse : 内部属性 , 用于标识根 BeanDefinition
        1- Class<?> resolvedClass = resolveBeanClass(mbd, beanName) -> PS:M173_02_01
            ?- 解析获得指定 BeanDefinition 的 class 属性 -> M173_04
        IF- 解析的 Class 不为 null , 且存在 BeanClass 和 BeanClassName
            - new RootBeanDefinition(mbd)
            - mbdToUse.setBeanClass(resolvedClass)
        2- mbdToUse.prepareMethodOverrides() : 处理 Overrides 属性 -> PS:M173_02_02
             - GetMethodOverrides().getOverrides()
             - prepareMethodOverride(MethodOverride mo)
        3- Object bean = resolveBeforeInstantiation(beanName, mbdToUse) --- 实例化的前置处理
        - 如果 bean 不为 null , 则直接返回 (直接返回是因为上一步生成了一个代理类 ,AOP )
        4- Object beanInstance = doCreateBean(beanName, mbdToUse, args); --- 创建对象
    M173_03- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    M173_04- resolveBeanClass : 将bean类名解析为class引用  

// PS:M173_02_01 RootBeanDefinition
// 确保bean类在此时被实际解析,如果动态解析的class不能存储在共享合并bean定义中,则克隆bean定义
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
}

// PS:M173_02_02 prepareMethodOverrides 处理 Overrides
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    if (hasMethodOverrides()) {
        getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
    }
}

// >>>>>>> 对应 prepareMethodOverride 方法
C- AbstractBeanDefinition
    M-  prepareMethodOverride(MethodOverride mo)
        1- ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName())
            ?- 获取当前Method Name 对应的方法数量
        2- 如果没有对应方法 ,抛出 BeanDefinitionValidationException
        3- 如果 count = 1 , 将 Overloaded 标记为未重载 , 在后续调用的时候,可以直接找到方法而不需要进行方法参数的校验

// M173_02 源码简介
M- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    -  beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
    -  beanInstance = this.doCreateBean(beanName, mbdToUse, args); -> M173_05

doCreateBean 主流程

doCreate 分为几大步骤 :

 C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
    M173_05- doCreateBean(beanName, mbdToUse, args) : 创建 Bean 对象
        ?- 非代理对象的 常规Bean 创建 , 主要节点有以下几个
        - 准备 BeanWrapper : BeanWrapper 是对 Bean 的包装
        - 如果单例模型,则从未完成的 FactoryBean 缓存中删除
        - createBeanInstance(beanName, mbd, args) : 进入Bean 创建流程 , 创建一个 Bean 的封装 BeanWrapper
            ?- 这里的获取如果是单例 , 则直接获取 , 并且移除缓存中的对象
            ?- 否则调用 createBeanInstance 获取
        - instanceWrapper.getWrappedInstance();
            ?- 包装的实例对象
        - instanceWrapper.getWrappedClass();
            ?- 包装的实例对象的类型
    	IF- applyMergedBeanDefinitionPostProcessors
            ?- 如果有后置处理 , 则在此处进行后置处理 , synchronized 上锁
    	IF- addSingletonFactory
            ?- 如果是单例 , 且允许+ 存在循环依赖 , 则在此处进行单例模式的处理
    	- populateBean : 属性注入操作 -> M173_30
    	- initializeBean : 初始化 Bean
            ?- 此处会进行 Init-Method 的处理 ->  PS:M173_05_03
    	IF- getSingleton
            ?- 循环依赖情况 , 则会递归初始依赖 bean , 此处返回的是一个用于循环处理的空对象
            ?- 2种情况 , 返回早期对象或者 getDependentBeans 递归所有的 -> PS:M173_05_01
    	- registerDisposableBeanIfNecessary
    M173_07- prepareMethodOverrides
        - 获取所有的 Overrides , 并且依次调用 prepareMethodOverride -> M173_08

    M173_08- prepareMethodOverride
        - getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride)
            ?- Foreach 所有的 Overrides , 调用 prepareMethodOverride
    M173_10- autowireByName : 根据属性名称,完成自动依赖注入
    M173_11- autowireByType : 根据属性类型,完成自动依赖注入
        - resolveDependency -> resolveDependency
    M173_12- resolveDependency : 完成了所有注入属性的获取
        - doResolveDependency
    M173_13- doResolveDependency
    M173_15- applyPropertyValues : 应用到已经实例化的 bean 中
    M173_50- initializeBean

// doCreateBean 核心代码流程
M- doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) : createBean 主流程
    - mbd.isSingleton() : 判断后获取 BeanWrapper (ConfigurationClassPostProcessor)
        - instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        - instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    - this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    - this.populateBean(beanName, mbd, instanceWrapper) : 主要是属性填充
        - Step 1 : bw == null&&mbd.hasPropertyValues() : BeanWrapper 空值判断
        - Step 2 : this.getBeanPostProcessors().iterator() : 迭代BeanPostProcessors
            - ibp.postProcessAfterInstantiation : 此处是 After
        - Step 3 : 获取 PropertyValue , 并且通过 autowireByName 或者 autowireByType 注入
        - Step 4 : hasInstantiationAwareBeanPostProcessors
            - this.getBeanPostProcessors().iterator();
            - ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
        - Step 5 :
        - Step 6 : this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs) : 依赖检查
        - Step 7 : this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs) :
    - this.initializeBean(beanName, exposedObject, mbd);
    - this.registerDisposableBeanIfNecessary(beanName, bean, mbd);     

// 附录 : M173_05 doCreateBean 源码比较长 ,放在结尾

PS:M173_05_01 : 递归循环细说

在 doCreateBean 中 , 会对循环依赖进行处理

// 循环依赖情况 , 则会递归初始依赖 bean , 此处返回的是一个用于循环处理的空对象
// 2种情况 , 返回早期对象或者 getDependentBeans 递归所有的
if (earlySingletonExposure) {
    // 参考循环依赖那一章 , 这里可能会返回一个未完善的前置对象引用
    // 只有存在循环依赖 , 这里才不会为空
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        // 判断存在循环依赖
        }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            // 返回依赖于指定bean的所有bean的名称(如果有的话)
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
                // 如果有被用于类型检查之外的其他目的时 ,则不可以删除 -> PS:M173_05_03
                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                    // 无需删除 , 则添加
                    actualDependentBeans.add(dependentBean);
                }
            }
            // 因为上文添加 , 这里就形成依赖
            if (!actualDependentBeans.isEmpty()) {
                throw new BeanCurrentlyInCreationException(".....");
            }
        }
    }
}

// PS:M173_05_03 : 什么是其他的目的 ?
removeSingletonIfCreatedForTypeCheckOnly 核心是校验 alreadyCreated
1 . 如果 alreadyCreated 已经存在了 ,则说明对应的对象已经创建完成了
2 . 如果对应的对象已经创建完了了 , 其中依赖的当前对象不是正在创建的对象
3 . 但是其中的属性又不是当前的对象 , 说明循环依赖不成立 , 依赖已经串了

@ https://www.cnblogs.com/qinzj/p/11485018.html

M173_05 doCreateBean 源码

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {

        // Step 1 : 准备 BeanWrapper : BeanWrapper 是对 Bean 的包装
        BeanWrapper instanceWrapper = null;

        if (mbd.isSingleton()) {
            // 如果单例模型,则从未完成的 FactoryBean 缓存中删除
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 进入Bean 创建流程 , 创建一个 Bean 的封装 BeanWrapper
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 获取包装的实例对象
        final Object bean = instanceWrapper.getWrappedInstance();
        // 包装的实例对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        //  Step 2 : 如果有后置处理 , 则在此处进行后置处理 , synchronized 上锁
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException("....");
                }
                mbd.postProcessed = true;
            }
        }

        // Step 3 :如果是单例 , 且允许+ 存在循环依赖 , 则在此处进行单例模式的处理
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {

            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Step 4 : 此处会进行 Init-Method 的处理 ->  PS:M173_05_03
        Object exposedObject = bean;
        try {
            // Step 5 :属性注入操作 -> M173_30
            populateBean(beanName, mbd, instanceWrapper);
            // Step 6 : 初始化 Bean
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException("....");
            }
        }

        // 循环依赖情况 , 则会递归初始依赖 bean , 此处返回的是一个用于循环处理的空对象
        // 2种情况 , 返回早期对象或者 getDependentBeans 递归所有的 -> PS:M173_05_01
        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 new BeanCurrentlyInCreationException(".....");
                    }
                }
            }
        }

        // Step 7 : 注册 Bean
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException("...");
        }

        return exposedObject;
    }

总结

其中有几个锚点 :

Step 1 : 入口

入口中主要是会统筹管理 , 如果缓存中有 , 则直接使用 , 如果没有 , 则区别 Scope 分别使用不同的方式获取一个 Bean

- C171- AbstractBeanFactory
    - M171_02- doGetBean

Step 2 : 创建主流程

创建主流程就是创建一个完整的 Bean , 走一个 Bean 创建的完整周期 , 包括 process , 属性注入 , init 初始化等等 , 这些我们在后面的文章中再详细说说

// Step 1 :
C173- AbstractAutowireCapableBeanFactory
    M173_02- createBea

// Step 2 :
C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
    M173_05- doCreateBean

附录

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        // 阶段一 : 生成 beanName 后尝试从单例缓存中获取
        final String beanName = transformedBeanName(name);
        Object bean;

        // 单例方式获取一个 Bean , 循环依赖就是这个环节处理 -> -> PS:M171_02_02
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            // 直接从实例化中获取 Bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 阶段二 : 单例缓存中获取失败后
            if (isPrototypeCurrentlyInCreation(beanName)) {
                //  如果是原型模式且存在循环依赖则抛出异常
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 检查这个工厂中是否存在bean定义
            BeanFactory parentBeanFactory = getParentBeanFactory();

            //  如果工厂中已经存在了 , 会有四种情况会直接 return -> PS:M171_02_03
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            //  如果为类型检查而获取实例,而不是实际使用 , 则将指定的bean标记为已经创建 -> PS:M171_02_04
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // RootBeanDefinition的获取和检查  LV171_001
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 阶段三 : 依赖检查 , 保证初始化当前bean所依赖的bean
                // 对于属性 LV171_001:mbd , 通过 getDependsOn 获取所有依赖
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    //  循环所有的依赖 , 分别调用 registerDependentBean + getBean 进行递归操作
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(.....);
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(.....);
                        }
                    }
                }

                // 阶段四 : 三种不同的类型获得 Bean 实例
                // 判断 Bean 的类型不同创建 Bean -> PS:M171_02_05
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(....);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 阶段五 : 此时 Bean 已经准备完成了 , 此处检查所需的类型是否与实际bean实例的类型匹配
        // 如果实例不匹配 , 则需要转换, 转换后直接返回
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        // 如果上面没有返回 , 则直接发返回原本的Bean
        return (T) bean;
    }

参考与感谢

写这个之前 , 还跑过去再读了一遍 , 很感谢死磕系列开启了 IOC 的源码学习

-> @ topjava.cn/article/139…

以上就是Spring IOC:CreateBean环节中的流程转换的详细内容,更多关于Spring IOC CreateBean的资料请关注我们其它相关文章!

(0)

相关推荐

  • 基于springioc bean 的几个属性介绍

    1.lazy-init="false" 默认值为false,指的是bean的创建时机的spring容器一启动就会加载这些类.有点是及时发现bean的相关错误,因为spring容器启动,bean也都会创建完毕,如果bean有什么差错都会报出,缺点就是如果bean对象的开销较大,那会提前占用内存. 如果设置为true,则等到spring容器去获取该bean的对象时才会创建.优缺点与false相反 2.scope="singleton" 默认值就是singleton,指的

  • Spring bean的实例化和IOC依赖注入详解

    前言 我们知道,IOC是Spring的核心.它来负责控制对象的生命周期和对象间的关系. 举个例子,我们如何来找对象的呢?常见的情况是,在路上要到处去看哪个MM既漂亮身材又好,符合我们的口味.就打听她们的电话号码,制造关联想办法认识她们,然后...这里省略N步,最后谈恋爱结婚. IOC在这里就像婚介所,里面有很多适婚男女的资料,如果你有需求,直接告诉它你需要个什么样的女朋友就好了.它会给我们提供一个MM,直接谈恋爱结婚,完美! 下面就来看Spring是如何生成并管理这些对象的呢? 1.方法入口 o

  • 详解SpringIOC BeanDeifition

    BeanDefiton是什么? BeanDefition是Spring对POJO的抽象,通过BeanDefition来更好地创建.管理Bean. 定义 含义 beanClassName bean的类名.该属性并不总是对应着bean真正使用的类的名称.bean通过某个类的静态工厂方法生成,那么这beanClassName就是该类:bean通过工厂Bean生成,那么这里为null scope 作用域 singleton 或者 prototype lazyInit 是否懒加载 BeanFacotry中

  • Spring IOC原理补充说明(循环依赖、Bean作用域等)

    前言 通过之前的几篇文章将Spring基于XML配置的IOC原理分析完成,但其中还有一些比较重要的细节没有分析总结,比如循环依赖的解决.作用域的实现原理.BeanPostProcessor的执行时机以及SpringBoot零配置实现原理(@ComponentScan.@Import.@ImportSource.@Bean注解的使用和解析)等等.下面就先来看看循环依赖是怎么解决的,在此之前一定要熟悉整个Bean的实例化过程,本篇只会贴出关键性代码. 正文 循环依赖 首先来看几个问题: 什么是循环依

  • 详解Spring框架---IOC装配Bean

    IOC装配Bean (1)Spring框架Bean实例化的方式提供了三种方式实例化Bean 构造方法实例化(默认无参数,用的最多) 静态工厂实例化 实例工厂实例化 下面先写这三种方法的applicationContext.xml配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"

  • 关于SpringBoot获取IOC容器中注入的Bean(推荐)

    一: 注入一个TestUtils类 package com.shop.sell.Utils; import com.shop.sell.dto.CartDTO; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TestUtils { @Bean(name="test

  • 浅谈springioc实例化bean的三个方法

    1.构造器 也就是在上一篇讲的那个例子,调用默认的无参构造函数 2.静态工厂方法 1)创建需要执行的方法的类 public class HelloWorld { public HelloWorld(){ System.out.println("aaaa"); } public void hello(){ System.out.println("hello world"); } } 2)创建静态工厂 public class HelloWorldFactory { p

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • spring ioc的简单实例及bean的作用域属性解析

    IoC(Inversion if Control)-控制反转是Spring俩大核心技术之一,IoC一般分为俩种类型:依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup) 使用示例: 1.新建工程并导入Spring相关jar包. 2.新建数据访问层及业务逻辑层 代码结构: 代码示例: /** * 实体Bean * @author BC * */ public class User { private Integer id; private

  • spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean实例放入bean缓存池: 应用程序使用bean. 1.2.基于xml的配置 (1)xml文件概述 xmlns------默认命名空间 xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件 xmlns:xxx="aaaaa"-------自定义命名空间,xx

  • 详解SpringIOC容器中bean的作用范围和生命周期

    bean的作用范围: 可以通过scope属性进行设置: singleton 单例的(默认) prototype 多例的 request 作用于web应用的请求范围 session 作用于web应用的会话范围 global-session 作用于集群环境的会话范围(全局会话范围) 测试: <!-- 默认是单例的(singleton)--> <bean id="human" class="com.entity.Human"></bean&g

  • Spring IOC装配Bean过程解析

    Spring的依赖注入 Spring主要支持两种依赖注入方式,分别是属性注入和构造函数注入.同时也支持工厂方法注入方式. 属性注入 属性注入的方式非常简单,即指通过setXxx()方法注入Bean的属性值或依赖对象.如下实例 编写User类 public class User { private String username; private String address; public User() { } public User(String username, String addres

随机推荐