Spring中的循环依赖问题

本文主要讲解Spring循环依赖问题。循环依赖指对象间构成环形调用,若Spring未处理会导致无限循环。为解决此问题,Spring提供三级缓存存储方式,文中还通过图解展示处理过程,并总结各级缓存作用,无AOP时一、三级缓存即可解决问题。

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


前言

本文章将讲解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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值