在Spring中如何处理循环依赖问题
Spring如何处理循环依赖
解决的关键就在于提前曝光未完全创建的bean。
在Spring中创建Bean分为三步
- 实例化,createBeanInstance,即new一个bean对象。
- 属性填充,populateBean,即往bean对象中set属性值。
- 初始化,initializeBean。
循环依赖的解决思路
- 先创建A的bean实例,此时的A是不完整的,因为没有属性填充(即B依赖没有注入),此时用一个Map保存不完整的A,
- 再创建B,B需要注入A,所以可以从Map中得到不完整的A,此时B就完整了,然后A就可以注入B了。
在Spring中,只有同时满足以下两点才能解决循环依赖的问题。
1.依赖的bean必须都是单例。
- 因为如果是原型模式的话是需要创建一个新的对象,创建A1的时候,需要创建A1的依赖B1
- 那么在创建B1的时候,又需要创建B1的依赖A2,这样就要创建B2,A3,B3……,进入无限的创建对象的过程
2.依赖注入的方式,不能全是构造函数注入。
- 如果全是构造函数注入,即A(B b) ,那么表明在创建A的Bean的实例的时候,就需要得到B,那么此时就要创建B的bean实例,但是B也是要在构造函数中注入A,即B(A a),此时B需要在Map中找到不完整的A,但是发现找不到,因为A的Bean实体还没创建完(还在等着B)。
- 注意:Spring容器是按照字母的顺序创建 Bean的,因此循环依赖中,字母排在前面的Bean不能采用构造函数注入。
Sping解决循环依赖全流程
首先了解Spring bean相关的三个Map
singletonObject
,存放所有创建完毕的单例bean(完整的bean,即已经完成实例化并进行属性填充)。earlySingletonObjects
,存放仅完成实例化,但未进行属性填充和初始化的Bean。singletonfactories
,存放能创建Bean的工厂,通过这个工厂能获得bean,延迟bean生成,工厂生成的bean会放到earlySingletonObjects中。
在实例化bean后,Spring是不知道当前bean有没有循环依赖的,它会义无反顾的往singletonfactories中存放当前bean的工厂,这个步骤就是提前曝光
然后开始属性注入,此时bean A发现要注入bean B,所以请执行getBean(B)
- 先去singletonObject里找有没有,如果有则进行返回
- 如果没有,则判断Bean是否在创建中,如果不在创建中,则返回null
- 如果在创建中,则去earlySingletonObjects找,如果有则进行返回
- 如果没有,则去singletonfactories找到这个bean的工厂,通过工厂去创建bean,并存放到earlySingletonObjects中
- 如果singletonfactories没有找到bean的工厂就返回null
- 如果返回null,说明bean还没有创建,这个时候会先把这个bean标记为创建中,再调用doCreateBean(即,实例化,属性填充,初始化三个步骤)
此时就到了B这个bean属性注入的步骤了,调用了getBean(A),A此时在singletonfactories中找到提前暴露的工厂的到了A,然后把A从singletonfactories中删除,放到earlySingletonObjects中。
此时B属性注入成功,然后进行初始化,最后B存放到singletonObject中。
此时又回到了A注入B的地方,完成了对B的注入,然后A也从earlySingletonObjects删除,存放到singletonObject中。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringCloud中分析讲解Feign组件添加请求头有哪些坑梳理
在spring cloud的项目中用到了feign组件,简单配置过后即可完成请求的调用。又因为有向请求添加Header头的需求,查阅了官方示例后,就觉得很简单,然后一顿操作之后调试报错...下面我们来详细了解2022-06-06华为鸿蒙系统应用开发工具 DevEco Studio的安装和使用图文教程
HUAWEI DevEco Studio 是华为消费者业务为开发者提供的集成开发环境(IDE),旨在帮助开发者快捷、方便、高效地使用华为EMUI开放能力。这篇文章主要介绍了华为鸿蒙系统应用开发工具 DevEco Studio的安装和使用图文教程,需要的朋友可以参考下2021-04-04Java使用Statement接口执行SQL语句操作实例分析
这篇文章主要介绍了Java使用Statement接口执行SQL语句操作,结合实例形式详细分析了Java使用Statement接口针对mysql数据库进行连接与执行SQL语句增删改查等相关操作技巧与注意事项,需要的朋友可以参考下2018-07-07Spring配置文件解析之BeanDefinitionParserDelegate详解
这篇文章主要介绍了Spring配置文件解析之BeanDefinitionParserDelegate详解,对于Spring的配置文件的解析处理操作是在BeanDefinitionParserDelegate中进行处理操作,接下来我们简单介绍一下BeanDefinitionParserDelegate所做的处理操作,需要的朋友可以参考下2024-02-02
最新评论