Spring源码-IOC之createBean

本文详细解析了SpringFramework6.0.9中createBean方法的工作原理,涉及bean实例化、方法覆盖验证、后置处理器调用、依赖注入等关键步骤,以及如何处理循环依赖和bean销毁逻辑。
摘要由CSDN通过智能技术生成

版本 Spring Framework 6.0.9​

1. createBean

createBean是AbstractBeanFactory的抽象方法,由其子类AbstractAutowireCapableBeanFactory实现。定义:创建一个完整的bean实例,包含填充bean属性,调用bean的后置处理等,是bean的生命周期一部分。
在这里插入图片描述

AbstractAutowireCapableBeanFactory#createBean步骤:

  1. 解析bean定义的beanClass属性,获取bean的对象类型。
  2. 验证bean定义所需的覆盖方法是否存在
  3. 调用InstantiationAwareBeanPostProcessor后置处理器(bean实例化之前的处理器,如果有)
  4. 调用doCreateBean方法实际创建指定的 Bean(1、2、3点都是预处理)
    在这里插入图片描述

1.1 resolveBeanClass

Spring源码-IOC之resolveBeanClass

在这里插入图片描述

1.2 prepareMethodOverrides

对Bean定义中的方法覆盖信息进行验证和准备,确保所有声明的重写方法有效。
判断bean定义中methodOverrides集合是否为空,并校验每个MethodOverride给定的名称方法在bean实际类型中是否存在。
在这里插入图片描述
在这里插入图片描述

1.3 resolveBeforeInstantiation

resolveBeforeInstantiation 方法是在实例化Bean之前调用的一个方法,调用InstantiationAwareBeanPostProcessor后置处理器(如果有),有机会返回一个代理对象替代实际的Bean实例。
这样,在实际创建Bean实例之前,就可能完成一些定制化的Bean创建逻辑,例如通过代理方式增强Bean的功能或完全替换Bean的实现。
在这里插入图片描述
在这里插入图片描述

1.4 doCreateBean

调用 doCreateBean 方法真正地创建Bean实例,该方法内部包括实例化、依赖注入、初始化等一系列操作。
在这里插入图片描述

2 doCreateBean

doCreateBean负责创建和初始化一个bean实例。通过调用createBeanInstance实例、MergedBeanDefinitionPostProcessor后置处理器修改合并后的bean定义(如果有)、populateBean填充bean的属性值、initializeBean调用bean的初始化方法(如果有)、以及将bean注册为可销毁的bean(如果实现了DisposableBean接口或提供了自定义的销毁方法)。
在这里插入图片描述

2.1 createBeanInstance

在这里插入图片描述

2.1.1 obtainFromSupplier

obtainFromSupplier方法负责从给定的Supplier获取bean实例,并返回一个保存了bean实例的BeanWrapper。该BeanWrapper设置了转换服务ConversionService和注册自定义PropertyEditor,为给定的BeanWrapper实例提供了丰富的类型转换和属性值处理能力。
在这里插入图片描述

2.1.2 applyMergedBeanDefinitionPostProcessors

调用类型为已注册的MergedBeanDefinitionPostProcessor的BeanPostProcessor,对给定的bean定义进行后处理。
在这里插入图片描述

getBeanPostProcessorCache方法返回一个存储不同类型的BeanPostProcessor的BeanPostProcessorCache对象
在这里插入图片描述

2.1.3 addSingletonFactory

创建了一个匿名lambda表达式作为ObjectFactory<?>参数,然后将这个lambda表达式及对应的bean名称传递给addSingletonFactory方法。确保在所有依赖项都被完全初始化之前就返回一个可用的bean引用,即是在解决一些循环依赖时,提前返回可用的bean引用(该bean未进行初始化)。
在这里插入图片描述

将给定的单例工厂与指定的bean名称关联起来,添加到singletonFactories中(三级缓存),这样做可以延迟bean实例的实际创建,直到真正需要时才通过单例工厂来生成,有助于优化内存使用和减少不必要的初始化开销。
在这里插入图片描述

getEarlyBeanReference方法返回一个未进行初始化的bean实例对象,并在满足特定条件时通过SmartInstantiationAwareBeanPostProcessor对其进行后处理。
在这里插入图片描述

2.1.4 populateBean

根据bean定义(mbd)和bean包装器(bw,包含bean实例)的信息,完成属性值的准备(自动装配)、后置处理器处理、依赖检查及最终的属性填充工作(applyPropertyValues方法)。在整个过程中,可能会因为各种条件(如bw为null、bean为Java记录类、后置处理器干预等)而提前结束属性填充流程。
在这里插入图片描述

applyPropertyValues方法将bean定义的属性值解析(resolveValueIfNecessary)并转换(convertForProperty)成bean对应属性的类型,填充(setPropertyValues)到bean中。
在这里插入图片描述

例子

比如下面的例子,用于展示applyPropertyValues的解析和转换简单过程,
设定两个对象User和Weapon。User对象设置了name、level属性,并且引用了weapon实例;Weapon对象设置了name属性,引用了user实例。
在这里插入图片描述

在这里插入图片描述

根据xml的配置,先解析User对象的name属性并给User对象属性赋值。原始值是TypedStringVaule,解析值是字符串的"魔法师",转换值还是字符串的"魔法师"
在这里插入图片描述
在这里插入图片描述

再解析User对象的level属性。原始值是TypedStringVaule,解析值是字符串的"1",转换值是整型的 1。
在这里插入图片描述
在这里插入图片描述

最后解析User对象的weapon,原始值是RuntimeBeanReference对象,解析值是weapon实例,转换后也是weapon实例。当然因为存在循环引用,在解析user的weapon属性时,会先去给weapon对象进行属性填充才赋值给user对象。
在这里插入图片描述
在这里插入图片描述

2.1.5 initializeBean

initializeBean方法依次执行Aware接口方法回调、前置和后置Bean后处理器处理,以及初始化方法调用,初始化给定的bean实例。
在这里插入图片描述

2.1.6 if (earlySingletonExposure) 抛出BeanCurrentlyInCreationException异常

doCreateBean中间有段代码,实际上是为了检查在循环引用场景中,验证当前bean是不是最终的封装版本。

举个例子,比如我们定义了一个名称为user的User对象和一个名称为weapon的Weapon对象,两个bean互相引用,但在User对象解析完成后,在bean工厂中名称为user的实际是一个Master对象,而weapon对象引用的是名称为user的User对象,不一致抛出BeanCurrentlyInCreationException异常。
已经注入weapon bean中的原始版本user bean与最终实际使用的封装版本Master bean不一致。因此,weapon bean并未使用到user bean的最终版本Master bean,导致异常。
在这里插入图片描述

这里只是为了展示如何走到抛出这个异常,解释这段代码场景,实际上我们可能不这么定义类去做实际项目。引发该异常有可能是后期的AOP代理、装饰器模式等。

引用上面的例子,创建一个Master类,继承User类。

在这里插入图片描述

添加一个后置处理器UserBeanPostProcessor,实现BeanPostProcessor接口,在postProcessAfterInitialization方法中将User对象替换一个Master对象(直接升级成99级,不再拿武器^^)。从上面的initializeBean方法中知道可以对bean实例后置处理。
在这里插入图片描述

在xml文件中,配置三个bean。
在这里插入图片描述

运行例子,输出如下:
在这里插入图片描述

解析:

  1. 首先 User 调用createBeanInstance实例化,并通过addSingletonFactory提前暴露,在填充属性populateBean的时候,发现自己依赖对象 Weapon,此时就会去尝试 get(Weapon),这个时候发现 Weapon 还没有被创建出来;
  2. 然后 Weapon 就走创建流程,从三级缓存中拿到A的引用,获取User的实例,Weapon创建并初始化完成。
  3. User 拿到 Weapon 后完成属性填充,调用initializeBean方法时调用UserBeanPostProcessor后置处理器,暴露Master对象。
  4. 此时原始bean User与暴露出的对象 Master不符合,User对象又依赖了 Weapon(其他bean),同时allowRawInjectionDespiteWrapping默认为false,表示不允许非原始注射,则抛出BeanCurrentlyInCreationException异常。
    在这里插入图片描述
    在这里插入图片描述

2.1.7 registerDisposableBeanIfNecessary

为需要进行销毁操作的非原型bean注册一个DisposableBeanAdapter适配器,用于管理该bean的销毁逻辑。
在这里插入图片描述

2.7.1.1 DisposableBeanAdapter构造方法

DisposableBeanAdapter构造函数通过初始化相关属性,为后续正确管理和调用bean的销毁方法做好准备。这些属性包括bean实例本身、bean名称、访问非公共销毁方法的权限标志、是否直接调用DisposableBean接口的destroy方法、是否有自定义销毁方法以及销毁bean后置处理器
在这里插入图片描述

2.7.1.2 DisposableBeanAdapter销毁方法

destroy方法按优先级依次触发前置销毁处理器、DisposableBean接口的destroy方法、AutoCloseable接口的close方法以及自定义的destroyMethod方法。在这里插入图片描述

参考

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值