Spring中如何解决循环依赖

目录

一、什么是循环依赖

二、Spring中会出现循环依赖的情况

三、如何解决Spring在单例模式下的循环依赖


一、什么是循环依赖

简单来说,在Spring中对象的创建管理都是IOC容器帮我们做的,以默认单例的方式帮我们创建bean,但是会出现一个问题:对象A里面有个属性是B对象,B对象里面又有一个A对象。

@Component
class A {
    @Autowired
    private B b;
}
@Component
class B{
     @Autowired
     private A a;
}

不管先创建哪个对象,在属性赋值时都要需要另一个对象。假设创建A对象,需要属性赋值的时候,发现需要B对象,去创建B对象的时候,发现需要A对象,此时A对象还未创建完。

Bean A → Bean B → Bean A,依赖关系形成闭环就会形成循环依赖。

二、Spring中会出现循环依赖的情况

  1. 通过构造方法进行依赖注入时产生的循环依赖问题。
  2. 通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。
  3. 通过setter方法进行依赖注入且是在多例模式下产生的循环依赖问题。

在Spring中,只有第2种方式单例模式的循环依赖问题被解决了,其他两种方式在遇到循环依赖问题时依然会产生异常。

在构造方法注入的情况下,在new对象的时候就会堵塞住。

Spring在多例模式下的setter方法,每次调用一次getBean都会执行一次构造方法并且给属性赋值,会导致OOM问题的出现,因此不能解决循环依赖

Spring在单例模式下的setter方法依赖注入关键点在于上面代码中A对象已经实例化了,但还未完成初始化,B找不到A引起的循环依赖问题,如下图,

三、如何解决Spring在单例模式下的循环依赖

  •     一级缓存:保存beanName和创建Bean直接实例的关系(保存放已经经历了完整生命周期的Bean对象)
 private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
  •     二级缓存:保存beanName和创建Bean直接实例的关系(半成品对象)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
  •     三级缓存:保存beanName和创建Bean的工厂之间的关系(第二个是一个函数式接口的类型)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);


那么Spring在单例模式下的循环依赖问题主要是通过三级缓存, 将实例化和初始化分开进行

简述流程:

实例化A ----->创建A的对象工厂并放入singletonFactories中 ----->填充A的属性时发现取不到B------>实例化B------->创建B的对象工厂并放入singletonFactories中------->从singletonFactories中获取A的对象工厂并获取A填充到B中--------->将成品B放入singletonObjects,并从singletonFactories中删除B的对象工厂--------->将B填充到A的属性中----------->将成品A放入singletonObjects并删除A的对象工厂。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值