Spring Bean 循环依赖

在Spring框架中,Bean的创建和管理是其核心功能之一。然而,在复杂的应用系统中,Bean之间可能会形成循环依赖(Circular Dependency),这种情况如果不加以妥善处理,将会导致Spring容器在初始化时抛出异常。本文将深入探讨Spring Bean循环依赖的概念、Spring的解决机制以及我们如何在开发中避免或处理循环依赖。

什么是循环依赖?

循环依赖指的是两个或多个Bean之间通过构造函数、Setter方法或字段注入相互依赖,形成一个闭环。例如,Bean A依赖于Bean B,同时Bean B又依赖于Bean A,这就构成了一个典型的循环依赖。

常见的循环依赖场景

  • 构造函数注入:最容易导致循环依赖的注入方式,因为构造函数是在Bean完全初始化之前调用的,如果此时Bean A需要注入Bean B,而Bean B的初始化又需要Bean A,就会陷入死循环。
  • Setter方法注入:相对构造函数注入而言,Setter方法注入可以通过延迟注入的方式解决循环依赖问题。
  • 字段注入:字段注入的处理方式与Setter方法类似,但通常不推荐使用,因为它破坏了依赖的明确性和可读性。

Spring如何解决循环依赖?

三级缓存

Spring容器通过三级缓存机制解决了基于Setter方法的单例Bean的循环依赖问题。这三级缓存分别是:

  1. 一级缓存(SingletonObjects):存储完全初始化好的Bean,即所有依赖注入都完成的Bean。
  2. 二级缓存(EarlySingletonObjects):存储早期暴露的Bean对象,这些对象已经完成了实例化,但尚未进行属性填充(即依赖注入未完成)。
  3. 三级缓存(SingletonFactories):存储的是ObjectFactory,用于生成Bean的早期引用,以便在需要时能够获取到Bean的早期实例(尚未填充依赖)。

当Spring容器检测到循环依赖时,它会利用三级缓存来提前暴露Bean的早期引用,从而解决依赖注入问题。

流程简述

  1. 当Spring容器需要创建Bean A时,会先检查一级缓存中是否已存在Bean A的实例,如果不存在,则继续。
  2. 接着,Spring会尝试创建Bean A的实例,并将其ObjectFactory加入到三级缓存中。
  3. 随后,Spring在填充Bean A的依赖时,如果发现依赖的Bean B尚未创建,则开始创建Bean B。
  4. 如果Bean B也依赖于Bean A(即出现循环依赖),此时Spring会从三级缓存中获取Bean A的ObjectFactory,调用其getObject方法获取Bean A的早期引用,并将其注入到Bean B中。
  5. 接着,Spring完成Bean B的剩余初始化过程,并将其加入到二级缓存中。
  6. 当Bean B的初始化完成后,Spring回到Bean A的初始化流程,从二级缓存中获取Bean B的实例,完成Bean A的依赖注入和剩余初始化工作。
  7. 最后,将Bean A的实例加入到一级缓存中,供后续使用。
相关推荐
y25082 分钟前
《Object类》
java·开发语言
曙曙学编程4 分钟前
初级数据结构——树
android·java·数据结构
BestandW1shEs9 分钟前
彻底理解消息队列的作用及如何选择
java·kafka·rabbitmq·rocketmq
爱吃烤鸡翅的酸菜鱼11 分钟前
Java算法OJ(8)随机选择算法
java·数据结构·算法·排序算法
码蜂窝编程官方15 分钟前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
Viktor_Ye31 分钟前
高效集成易快报与金蝶应付单的方案
java·前端·数据库
hummhumm33 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
一二小选手38 分钟前
【Maven】IDEA创建Maven项目 Maven配置
java·maven
J老熊43 分钟前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程
猿java1 小时前
什么是 Hystrix?它的工作原理是什么?
java·微服务·面试