如何解决创建对象时的循环依赖问题

本文解释了依赖注入中循环依赖的概念,阐述了当A类依赖B类且B类依赖A类时如何导致Spring容器创建bean时的死锁问题。通过讲解三级缓存机制,展示了如何通过set方法避免循环依赖并确保对象完整创建。
摘要由CSDN通过智能技术生成

解释

依赖:DI(依赖注入)中的依赖,某一类中的属性需要在创建对象是给其赋值,这个依赖具体指的就是那个值

循环:当依赖是自定义类(javabean)时,A类中有一个B类型的外部属性b,B类中有个A类型的外部属性a

循环依赖:当spring容器创建A类对象或创建B类对象时,以创建A类对象为例,实例化A时需要B类对象,那就需要创建B类对象,创建B类对象时又需要A类对象,但是创建A类对象又需要B类对象,导致两个对象创建时一直等待依赖双方的对象创建出来,僵持不下,导致类似死锁的局面

循环依赖出现的场景

DI(依赖注入),多个类之间相互需要彼此作为创建完整对象的部分内容,相互之间的依赖关系形成闭环

循环依赖的成因

spring容器创建完整的bean对象需要经历的各个阶段

以A类依赖B类,B类依赖A类,具体看依赖循环成因

spring容器创建A对象,在进行初始化时需要属性赋值时(给外部属性赋B对象),停止继续初始化,转头去容器中找是否有B对象,没有,则创建B对象,当走到属性赋值时需要A对象,发现A类和B类有循环依赖关系报错。

BeanCreationException: Error creating bean with name 'a' defined in class path resource [applicationConfig.xml]: Cannot resolve reference to bean 'b' while setting constructor argument;

创建A对象时未解决与B的依赖关系

BeanCreationException: Error creating bean with name 'b' defined in class path resource [applicationConfig.xml]: Cannot resolve reference to bean 'a' while setting constructor argument

创建B对象时未解决与A的依赖关系

BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?

创建当前bean时可能有循环依赖问题未解决

当依赖注入方式采用构造方法,出现上面错误信息

当依赖注入采用set方法时,spring容器自动处理了依赖注入问题

解决办法

依赖注入时,有类与类之间相互依赖的情况,选择set注入方式,spring容器自动解决循环注入问题

解决原理

三级缓存

三级缓存:存未被引用的bean半成品

二级缓存:存被引用的bean半成品

一级缓存:存完整的bean

当A对象初始化进入到属性赋值时,发现需要B对象,去三级缓存找没找到,将自己这个半成品存到三级缓存

B对象创建进入到属性赋值阶段,发现需要A对象,去三级缓存找找到了,走完初始化得到完整的B对象放入一级缓存,删除二、三级缓存中的B对象半成品,A对象半成品从三级到二级

A继续属性赋值,三级、二级都没有B对象在一级缓存中找到,A对象继续其他步骤完成创建,删除二、三级缓存中A的内容,完整的A对象放入一级缓存

疑惑地点:A对象中的B貌似是半成品,B对象中的A也貌似是半成品。完成和半成品只是对象的两个时期的状态,最终引用的都是地址,当A对象创建走完初始化全过程,B对象原来指向“半成品”最终就指向完成品,同理A对象中指向的也是完整的B对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值