Spring通过三级缓存机制来解决单例Bean的Setter或字段注入类型的循环依赖问题。以下是Spring解决循环依赖的核心流程:

1. 三级缓存介绍

Spring容器为了解决循环依赖,维护了以下三个缓存:

  • 一级缓存(singletonObjects):已完全初始化的单例Bean。
  • 二级缓存(earlySingletonObjects):早期暴露的Bean(未完全初始化,但已注入必要属性)。
  • 三级缓存(singletonFactories):存储创建Bean的工厂,允许获取Bean的代理对象。

2. 解决循环依赖的关键流程

以下是Spring处理循环依赖的步骤:

  1. 创建Bean实例

    Spring在实例化一个Bean时,首先会在一级缓存中查找。如果未找到,会尝试通过三级缓存提前暴露一个工厂,用于生成当前正在创建的Bean的早期引用。

  2. 将早期引用暴露到三级缓存

    Spring在Bean实例化之后,尚未填充属性之前,会将Bean的ObjectFactory(一个创建Bean早期引用的工厂)存入三级缓存。

  3. 填充依赖

    在填充Bean的依赖时,如果发现需要依赖另一个Bean且该Bean正在创建中,Spring会从三级缓存中获取早期引用,并注入到当前Bean中。

  4. 完成初始化

    当Bean完成属性注入并经过初始化回调后,Spring会将完全初始化的Bean移入一级缓存,同时从二级和三级缓存中移除该Bean的引用。

3. 示例代码

以循环依赖为例:

@Component
public class BeanA {
@Autowired
private BeanB beanB;
} @Component
public class BeanB {
@Autowired
private BeanA beanA;
}

Spring解决的流程:

  1. 初始化BeanA,发现依赖BeanB;
  2. 开始初始化BeanB,发现依赖BeanA;
  3. 从三级缓存中获取BeanA的早期引用,将其注入到BeanB;
  4. BeanB完成初始化,存入一级缓存;
  5. 返回继续完成BeanA的初始化。

4. 注意事项

  1. 仅适用于单例作用域

    Spring的三级缓存机制仅适用于单例Bean。Prototype作用域的Bean不受容器管理,无法提前暴露早期引用,因此无法解决循环依赖。

  2. 构造器注入无法解决

    构造器注入要求在实例化时提供完整依赖,而此时无法提前暴露引用,Spring会直接抛出BeanCurrentlyInCreationException。

5. 如何避免循环依赖

虽然Spring能够解决部分循环依赖,但实际开发中,建议通过以下方式避免:

  • 优化设计,拆分循环依赖。
  • 使用@Lazy懒加载,延迟依赖的注入时机。
  • 引入接口或事件机制,解耦Bean之间的直接依赖。

总结:

Spring通过三级缓存机制解决了Setter和字段注入的循环依赖问题,而构造器注入和Prototype作用域需要开发者自行设计规避。

Spring 如何解决循环依赖?的更多相关文章

  1. Spring 如何解决循环依赖问题?

    在关于Spring的面试中,我们经常会被问到一个问题,就是Spring是如何解决循环依赖的问题的. 这个问题算是关于Spring的一个高频面试题,因为如果不刻意研读,相信即使读过源码,面试者也不一定能 ...

  2. Spring如何解决循环依赖问题

    目录 1. 什么是循环依赖? 2. 怎么检测是否存在循环依赖 3. Spring怎么解决循环依赖 本文主要是分析Spring bean的循环依赖,以及Spring的解决方式. 通过这种解决方式,我们可 ...

  3. Spring 如何解决循环依赖的问题

    Spring 如何解决循环依赖的问题 https://blog.csdn.net/qq_36381855/article/details/79752689 Spring IOC 容器源码分析 - 循环 ...

  4. 一张图彻底理解Spring如何解决循环依赖!!

    写在前面 最近,在看Spring源码,看到Spring解决循环依赖问题的源码时,不得不说,源码写的太烂了.像Spring这种顶级的项目源码,竟然存在着这种xxx的代码.看了几次都有点头大,相信很多小伙 ...

  5. Spring如何解决循环依赖

    一.什么是循环依赖 多个bean之间相互依赖,形成了一个闭环. 比如:A依赖于B.B依赖于c.c依赖于A 通常来说,如果问spring容器内部如何解决循环依赖, 一定是指默认的单例Bean中,属性互相 ...

  6. Spring中解决循环依赖报错的问题

    什么是循环依赖 当一个ClassA依赖于ClassB,然后ClassB又反过来依赖ClassA,这就形成了一个循环依赖: ClassA -> ClassB -> ClassA 原创声明 本 ...

  7. Spring如何解决循环依赖,你真的懂了?

    导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...

  8. Spring如何解决循环依赖?

    介绍 先说一下什么是循环依赖,Spring在初始化A的时候需要注入B,而初始化B的时候需要注入A,在Spring启动后这2个Bean都要被初始化完成 Spring的循环依赖有两种场景 构造器的循环依赖 ...

  9. 彻底理解Spring如何解决循环依赖

    Spring bean生命周期 可以简化为以下5步. 1.构建BeanDefinition 2.实例化 Instantiation 3.属性赋值 Populate 4.初始化 Initializati ...

  10. 【Spring】 Spring如何解决循环依赖的问题?

    https://mp.weixin.qq.com/s/FtbzTMxHgzL0G1R2pSlh-A 通常来说,如果问Spring内部如何解决循环依赖,一定是单默认的单例Bean中,属性互相引用的场景. ...

随机推荐

  1. 牛客 acm输入输出模式练习

    https://www.nowcoder.com/exam/test/67432019/detail?pid=27976983#question 注意:只有部分个人觉得有意义的题目 A+B(4) 计算 ...

  2. Svelte 最新中文文档翻译(5)—— 基础标记

    前言 Svelte,一个非常"有趣".用起来"很爽"的前端框架.从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 ...

  3. Python 与 PostgreSQL 集成:深入 psycopg2 的应用与实践

    title: Python 与 PostgreSQL 集成:深入 psycopg2 的应用与实践 date: 2025/2/4 updated: 2025/2/4 author: cmdragon e ...

  4. DeepSeek-R1 技术全景解析:从原理到实践的“炼金术配方” ——附多阶段训练流程图与核心误区澄清

    字数:约3200字|预计阅读时间:8分钟 (调试着R1的API接口,看着控制台瀑布般流淌的思维链日志)此刻我仿佛看到AlphaGo的棋谱在代码世界重生--这是属于推理模型的AlphaZero时刻. D ...

  5. Linux安装hive

    1.需要先安装hadoop以及mysql,参考其他文章 安装hive和hadoop都在hadoop用户目录下 2.安装hive,之前,先在mysql上创建一个hive,数据库,并在hive数据库中建立 ...

  6. dotnet CLI推送Nuget

    前提: 准备好要发布的包 选择一个打包工具,可以是dotnet CLI.nuget.exe CLI.MSBuild 准备好Nuget官方API Key 自述文件   先必须添加Readme.md到项目 ...

  7. 鸿蒙开发 - 数据持久化 Preferences (内存存储) (封装)

    这篇文章介绍鸿蒙中的 Preferences,它是一种轻量级存储方式,数据存储在内存中,用于存储少量的数据. 可以执行 flush() 方法将内存中的数据写入到磁盘文件,保证下次重启后数据可以继续使用 ...

  8. 试试使用 Vitest 进行测试,确实可以减少bug

    vitest的简单介绍 Vitest 是一个基于 Vite 的单元测试框架,专为现代前端项目设计. 它结合了 Vite 的高性能和 Jest 的易用性, 提供了开箱即用的 TypeScript.ESM ...

  9. Python基础-模块和面向对象-shutil、re、bs4、requests模块

    概要: 模块 自定义模块(已经讲了) 内置模块 shutil re 正则表达式 第三方模块 requests 模块 bs4 模块 面向对象: 面向对象(Object-Oriented Programm ...

  10. word 批量制作ppt

    将 Word 文档作为大纲,构建演示文稿 在 Word 文档中,单击"开始". 使用"样式"设置 Word 文档中内容的格式. 突出显示要用作幻灯片标题的内容, ...