Spring中的循环依赖问题


前言

本文章将讲解Spring循环依赖的问题


一、什么是循环依赖?

一个或多个对象之间存在直接或间接的依赖关系,这种依赖关系构成一个环形调用,有下面 3 种方式。

![在这里插入图片描述](https://img-blog.csdnimg.cn/3142f6a04b31455f853e4f1403c0ea29.png

模拟一个情况2的Demo

@Service
public class Service {
	@Autowried
	Dao dap;
}
@Repository
class Dao{
	@Autowried
	Service service;
}

在这里插入图片描述

这是一个经典的循环依赖,如果spring没有处理循环依赖,那么在他们需要注入对方属性时,会一直循环等待对方注入属性,导致无限循环。

二、三级缓存

Spring为了解决循环引用的问题,提供了三级缓存的存储方式

public class DefaultSingletonBeanRegistry ... {
//1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存"
Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存"
Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
//3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三
级缓存"
Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
}
注:将对象保存至三级缓存的时候,会包装成ObjectFactory对象录入,未来通过此接口对应的get方法再
次提取对象

三、图解

在这里插入图片描述

图解描述:

  • A实例化对象,但尚未初始化,将A存储到三级缓存中;
  • A属性注入,发现需要B对象,从缓存中取,发现没有B对象;
    • B实例化对象,但尚未初始化,将B放到三级缓存
    • B属性注入,需要A对象,从三级缓存中通过工厂获取A对象,再将A从三级缓存移除到二级缓存,
    • B执行其他生命周期的过程,最终成为一个完全体Bean,存储到一级缓存,删除二三级缓存
  • A注入B对象
  • A执行其他生命周期过程,最终成为一个完全体Bean,存储到一级缓存,删除二三级缓存

三级缓存总结

  • 一级缓存:为“Spring 的单例属性”而生 ,就是个单例池,用来存放已经初始化完成的单例 Bean;
  • 二级缓存:为“解决 AOP”而生 ,存放的是半成品的 AOP 的单例 Bean;
  • 三级缓存:为“打破循环”而生 ,存放的是生成半成品单例 Bean 的工厂方法

如果没有AOP的话,其实只需要一、三级缓存,就可以解决循环引用的问题;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值