从Spring容器刷新过程中的创建Bean阶段来说说Bean的生命周期

41 篇文章 8 订阅
26 篇文章 6 订阅

从Spring容器刷新过程中的创建Bean阶段来说说Bean的生命周期

我们所说的Bean的生命周期指的是从Bean的创建、初始化、使用Bean、销毁的整个过程。而IOC容器就是负责管理Bean的整个生命周期。实际上Bean的生命周期在容器启动的时候就已经开始了,严格来说,你可以认为容器启动时,从注解配置读取器读取标有注解的类,转换为BeanDefinition对象时,Bean的生命周期就已经开始了。打个比方,小宝宝的生命的起点,并不是说从出生落地开始算的,而是从妈妈肚子里面,基本上可以算是生命已经开始了。

我们在之前的IOC容器创建过程的文章中详细说明了容器的初始化和容器刷新的流程。我们说在执行refresh()方法刷新容器时,第11个阶段是创建剩余的所有单实例Bean

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UYBDPMgz-1632768559832)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927165619780.png)]
​首先遍历所集合中所有的Bean,根据Bean的name调用getBean()方法获取这个Bean
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sc7ZwX1a-1632768559836)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927170346253.png)]

getBean()方法进一步调用doGetBean()方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oMxBhNiV-1632768559839)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927010651741.png)]
拿到bean的名字之后,先调用getSingleton()方法获取缓存中的单实例bean,如果能获取到,就说明这个bean之前已经被创建过了,因为所有创建过的单实例bean都会被缓存起来。
在这里插入图片描述

注意!如果缓存中获取不到,才算是真正开始创建Bean对象的流程!!!

首先标记当前bean已被创建,防止多线程创建同一个bean
在这里插入图片描述
然后获取bean定义信息,以及当前bean依赖的其它bean,如果有依赖就会调用getBean()方法把依赖的bean先创建出来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-740H2gaW-1632768559847)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927011148129.png)]
如果当前bean是单实例bean,就会启动单实例bean创建流程,会调用getSingleton()方法通过工厂的getObject()方法调用createBean()来创建bean。也就是说真正执行创建Bean的方法是这个createBean()方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xsdWcAyU-1632768559848)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927011619983.png)]

那么接下来就来详细说一说createBean()方法是如何创建Bean的

createBean()会先获取bean的定义信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABm0QUoE-1632768559850)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927011739478.png)]
然后解析bean的类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3YkNgmH-1632768559853)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927012635531.png)]

在Bean实例化之前,createBean()会调用resolveBeforeInstantiation()方法,会给Bean的后置处理器一个机会,**在实例化之前,让BeanPostProcessor先拦截返回代理对象,在实例化之前执行一些自定义逻辑,同时也会在实例化之后执行一些自定义逻辑。**也就是说,可以利用Bean的后置处理器,在Bean实例化前后的时间点,去执行一些我们自定义的操作逻辑。

如果说在这个Bean实例化之前,这个BeanPostProcessor后置处理器返回的代理对象不为null,就会直接返回这个代理对象。此时相当于跳过了容器默认的实例化过程,用这个代理对象替代了本该实例化的Bean对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bnqb7IKl-1632768559856)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927181110136.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwLcPd1V-1632768559859)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927190349944.png)]

如果前面的resolveBeforeInstantiation()方法没有返回一个代理对象,就会调用doCreateBean()方法去创建Bean对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zIgmeqLi-1632768559861)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927193245737.png)]

实际上这个doCreateBean()方法会调用createBeanInstance()方法创建一个bean实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6AKSgpCn-1632768559862)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927193433685.png)]

createBeanInstance()方法利用工厂方法或者对象的构造器创建出bean实例
在这里插入图片描述

doCreateBean()方法完成bean的创建之后,会调用populateBean()为创建出来的bean进行属性赋值。上面我们所说的由于直接返回代理对象,没有执行属性赋值,可以防止恶意的属性注入操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VkSYiSh1-1632768559869)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927193844299.png)]

在赋值之前,会先获取BeanPostProcessor后置处理器,在实例化之后,初始化之前,利用这个后置处理器执行一些拦截操作。然后才是进行属性赋值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2DdgVZD3-1632768559875)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927194652200.png)]

完成属性赋值之后,会调用initializeBean()方法来初始化bean

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZ8xBrCY-1632768559876)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927195152255.png)]

initializeBean()方法会调用invokeAwareMethods()方法,执行各种实现了Aware接口的方法,比如设置bean的name、类加载器、beanFactory等信息。
在这里插入图片描述

然后调用applyBeanPostProcessorsBeforeInitialization()方法,后置处理器也会在bean初始化之前进行拦截
在这里插入图片描述

初始化之前的后置处理器执行完之后,就会调用invokeInitMethods()方法,执行初始化方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ByhG43kM-1632768559893)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927200928429.png)]

invokeInitMethods()方法执行bean的初始化操作,执行那些实现了InitializingBean初始化接口,或者那些自定义的初始化的方法(使用注解或者init-method属性)

在这里插入图片描述

初始化结束之后,还会调用applyBeanPostProcessorsAfterInitialization()方法,执行初始化之后的后置处理器操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XqEpDWVC-1632768559894)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927201542963.png)]

至此bean的初始化完成

初始化执行完成之后,会调用registerDisposableBeanIfNecessary()方法注册bean的销毁方法,容器关闭的时候或者移除这个Bean的时候会调用销毁方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RlurePB6-1632768559896)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927201749285.png)]

至此doCreateBean()方法执行结束,返回一个bean实例。整个doCreateBean()包含了实例化Bean、属性赋值、初始化Bean、注册销毁方法。

所以Spring容器的启动伴随着Bean生命周期的开始,整个Bean的生命周期如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0whmyLpH-1632768559897)(C:\Users\Jian\AppData\Roaming\Typora\typora-user-images\image-20210927202556861.png)]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值