Spring IOC循环依赖问题

本文详细介绍了Spring框架中的循环依赖问题,包括构造器和字段注解的依赖情况。Spring通过三级缓存机制解决单例Bean的循环依赖,对于原型Bean则直接报错。循环依赖的解决过程涉及到Bean的提前暴露,确保在对象初始化完成后能够正确设置属性,从而完成对象的完整构建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 什么是循环依赖

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如A依赖于B, B依赖于C, C⼜依赖于A。
在这里插入图片描述
注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件。
Spring中循环依赖场景有:
● 构造器的循环依赖(构造器注⼊)
● Field 属性的循环依赖(set注⼊)
其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决属性循环依赖时, spring采⽤的是提前暴露对象的⽅法。这也就解决了其中一个依赖的问题这样也就解决了循环依赖的问题了。

2. Spring IOC处理循环依赖

2.1 Bean对象类型和依赖注入方式

● 单例Bean
构造器注入形成的循环依赖无法解决
Set注入形成的循环的依赖可以解决
@Autoired注解方式注入形成的循环依赖可以解决
● prototype原型Bean
对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx⽅法产⽣循环依赖, Spring都会直接报错处理。

2.2 循环依赖处理机制

在Spring IOC中主要是通过三级缓存机制来处理循环依赖问题的:
第一级缓存: 单例池
第二级缓存:earlySingleton
第三级缓存:SingletonFactory
示例:ClassA依赖ClassB,ClassB依赖ClassA,这样也就形成了循环依赖的问题,Spring的IOC解决的方案如下图所示:
在这里插入图片描述
Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置的,但是构造器必须是在获取引⽤之前Spring通过setXxx或者@Autowired⽅法解决循环依赖其实是通过提前暴露⼀个ObjectFactory对象来完成的,简单来说ClassA在调⽤构造器完成对象初始化之后,在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。
● Spring容器容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器。
在这里插入图片描述

● ClassA调⽤setClassB⽅法, Spring⾸先尝试从容器中获取ClassB,此时ClassB不存在Spring容器中。
● Spring容器初始化ClassB,同时也会将ClassB提前暴露到Spring容器中。
● ClassB调⽤setClassA⽅法, Spring从容器中获取ClassA ,因为第⼀步中已经提前暴露了ClassA,因此可以获取到ClassA实例。ClassA通过spring容器获取到ClassB,完成了对象初始化操作。
● 这样ClassA和ClassB都完成了对象初始化操作,解决了循环依赖问题。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值