news 2026/6/10 15:06:33

一文详解Spring Bean的循环依赖问题及解决方案(三级缓存)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文详解Spring Bean的循环依赖问题及解决方案(三级缓存)

01-什么是Bean的循环依赖

A对象中有B属性,B对象中有A属性,这就是循环依赖。我依赖你,你也依赖我

例如:Bean A 依赖 Bean B,Bean B 依赖 Bean A

@Service public class ServiceA { @Autowired private ServiceB serviceB; // A 依赖 B } @Service public class ServiceB { @Autowired private ServiceA serviceA; // B 又依赖 A }

02-前置知识之Bean的作用域

singleton:默认情况下,Spring的IoC容器创建的Bean对象是单例的

prototype:原型。每调用一次getBean()方法则获取一个新的Bean对象每次注入的时候都是新对象

03-无法解决的循环依赖情况

prototype下的set注入产生的循环依赖:

  • 当循环依赖的所有Bean@Scope("prototype")的时候,产生的循环依赖,Spring是无法解决的,会出现BeanCurrentlyInCreationException异常;
  • 以上两个Bean,如果其中一个是singleton另一个是prototype,是没有问题

singleton下的构造注入产生的循环依赖:

  • 也会出现BeanCurrentlyInCreationException异常,产生了循环依赖,并且Spring是无法解决这种循环依赖的
  • 原因:通过构造方法注入导致的。因为构造方法注入会导致实例化对象的过程对象属性赋值的过程没有分离开,必须在一起完成导致的

04-Spring能解决的循环依赖情况 —— 面试

singleton下的set注入产生的循环依赖,Spring可以解决这个问题。为什么?

主要的原因是,在singleton + set注入模式下Spring对Bean的管理主要分为清晰的两个阶段:

  • 第一个阶段:在Spring容器加载的时候,实例化Bean,只要其中任意一个Bean实例化之后,马上进行 “曝光”【不等属性赋值就曝光】

  • 第二个阶段:Bean“曝光”之后,再进行属性的赋值(调用set方法)

  • 核心解决方案是:实例化对象对象的属性赋值分为两个阶段来完成的

注意:只有在scope是singleton的情况下,Bean才会采取提前“曝光”的措施

05-Spring解决循环依赖的机理 —— 面试

Spring为什么可以解决set + singleton模式下循环依赖?

根本的原因在于:这种方式可以做到将“实例化Bean”“给Bean属性赋值”这两个动作分开去完成

  • 实例化Bean的时候:调用无参数构造方法来完成。此时可以先不给属性赋值,可以提前将该Bean对象“曝光”给外界
  • 给Bean属性赋值的时候调用setter方法来完成

两个步骤是完全可以分离开去完成的,并且这两步不要求在同一个时间点上完成

也就是说,Bean都是单例的,我们可以先把所有的单例Bean实例化出来,放到一个集合当中(我们可以称之为缓存),所有的单例Bean全部实例化完成之后,以后我们再慢慢的调用setter方法给属性赋值。这样就解决了循环依赖的问题

那么在Spring框架底层源码级别上是如何实现的呢?请看:

在以上类中包含三个重要的属性:

  • Cache of singleton objects:bean name to bean instance.单例对象的缓存:key存储bean名称,value存储 Bean对象【一级缓存】

  • Cache of early singleton objects:bean name to bean instance.早期单例对象的缓存:key存储bean名称,value存储早期的 Bean对象【二级缓存】

  • Cache of singleton factories:bean name to ObjectFactory.单例工厂缓存:key存储bean名称,value存储该Bean对应的 ObjectFactory对象【三级缓存】

这三个缓存其实本质上是三个Map集合。
我们再来看,在该类中有这样一个方法addSingletonFactory(),这个方法的作用是:将创建Bean对象的ObjectFactory对象提前曝光

再分析下面的源码:

从源码中可以看到,spring会先从一级缓存中获取Bean,如果获取不到,则从二级缓存中获取Bean,如果二级缓存还是获取不到,则从三级缓存中获取之前曝光的ObjectFactory对象,通过ObjectFactory对象获取Bean实例,这样就解决了循环依赖的问题

06-总结

Spring只能解决setter方法注入的单例bean之间的循环依赖

ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环。

  • Spring在创建ClassA对象后,不需要等给属性赋值,直接将其曝光到 bean缓存 当中
  • 解析ClassA的属性时,又发现依赖于 ClassB,再次去获取 ClassB
  • 解析ClassB的属性时,又发现需要 ClassA 的属性
  • 此时的ClassA 已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA 的实例,直接从缓存中获取即可

从而解决循环依赖问题

07-如何避免出现循环依赖问题

1. 使用Setter注入替代 构造器注入;

2. 使用@Lazy 延迟加载

@Component public class ServiceA { @Lazy // 延迟初始化 @Autowired private ServiceB serviceB; }

3. 使用ApplicationContext 手动获取

@Component public class ServiceA { @Autowired private ApplicationContext context; public void method() { ServiceB b = context.getBean(ServiceB.class); } }

4. 使用ObjectProvider(推荐)

@Component public class ServiceA { @Autowired private ObjectProvider<ServiceB> bProvider; public void method() { ServiceB b = bProvider.getIfUnique(); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/5 11:31:47

最新网络安全行业入门全指南:前景、方向与实战学习路径

最新网络安全行业入门全指南&#xff1a;前景、方向与实战学习路径 在数据即资产的今天&#xff0c;网络安全早已不是黑客攻防的小众领域 ——2025 年国内网络安全人才缺口突破350万&#xff0c;渗透测试、安全研发等岗位起薪比普通 IT 岗位高 20%&#xff0c;3 年经验工程师年…

作者头像 李华
网站建设 2026/6/8 13:06:56

AI 如何改变 IT 行业:从工具到伙伴的深刻变革

引言 在过去的几年里,人工智能(AI)已经从科幻概念迅速演变为 IT 行业的核心驱动力。2025 年,我们看到 AI 不再是锦上添花的功能,而是深度融入开发、运维、安全、数据等几乎所有领域的底层技术。AI 的广泛应用正在重塑 IT 从业者的日常工作,既带来了效率的飞跃,也改变了…

作者头像 李华
网站建设 2026/6/8 21:36:59

14、网络信息系统(NIS):原理、配置与应用详解

网络信息系统(NIS):原理、配置与应用详解 1. 引言 在局域网环境中,为用户提供透明的网络体验是一个重要目标。其中,确保关键数据(如用户账户信息)在所有主机间同步至关重要,这能让用户自由切换设备,无需记忆不同密码或复制数据。虽然域名系统(DNS)在互联网上用于特…

作者头像 李华
网站建设 2026/6/10 5:03:33

git迁移代码到其他仓库的方法 个人记录

克隆只包含指定分支的仓库 git clone --single-branch --branch <branch-name> <原仓库URL>如&#xff1a; git clone --single-branch --branch develop-重构1128 http://xxxllm_platform/test.gitcd <repo-directory>添加新的远程仓库 git remote add ne…

作者头像 李华
网站建设 2026/6/9 4:37:57

PPT排版又丑又慢怎么办?这个“AI生成PPT”功能,3秒拯救你的PPT

你是不是也遇到过这样的情况&#xff1a;明明内容都想好了&#xff0c;可一做PPT就头疼&#xff1f;调字体、对格式、找图片、排版面……折腾好几个小时&#xff0c;做出来的PPT还是不好看。更让人崩溃的是&#xff0c;有时候半夜还在改PPT格式&#xff0c;就为了第二天早上开会…

作者头像 李华