当前位置: 首页 > news >正文

不加 @Lazy 一定会发生循环依赖,启动失败吗?

不加 @Lazy 一定会发生循环依赖,启动失败吗?

绝对不是。

不加@Lazy注解,并不代表一定会发生循环依赖或启动失败。@Lazy只是解决特定问题的“药”,而不是所有项目的“饭”。

为了让你彻底放心,我们需要把**“循环依赖”“启动失败”**这两个概念拆开来看。

🚫 情况一:根本没有循环依赖(最常见)

如果你的代码设计是清晰的树状或链状结构,比如:

  • Controller -> Service -> Dao
  • A -> B -> C

在这种情况下,完全不需要@Lazy。Spring 会按照顺序依次创建 C,然后 B,最后 A。一切运行完美,没有任何报错。

✅ 情况二:有循环依赖,但 Spring 能自动搞定(单例 + 字段注入)

这是 Spring 最强大的地方。如果你有以下场景:

  • A 和 B 互相依赖(A注入B,B注入A)
  • 都是单例(@Scope("singleton"),默认就是)
  • 使用字段注入(@Autowired在属性上) 或 Setter 注入

结论:不加@Lazy也能正常启动!

原理:
Spring 的三级缓存机制非常强大。它允许先创建一个“半成品”的 A(还没填属性),放入三级缓存;然后去创建 B,B 需要 A 时,Spring 从三级缓存里把那个“半成品 A”拿出来给 B 用。等 B 创建好了,再回头把完整的 B 塞给 A。

注意:这种情况下,虽然不加@Lazy能跑通,但如果你的项目升级到了 Spring Boot 2.6+,默认配置可能会禁止这种循环引用,这时你就需要在配置文件里开启spring.main.allow-circular-references=true,或者还是得加@Lazy

❌ 情况三:不加 @Lazy 必死无疑(必须加的场景)

只有在以下几种“硬骨头”场景下,不加@Lazy才会导致启动报错:

1. 构造器注入导致的循环依赖
@ServicepublicclassA{privatefinalBb;// 构造器注入:A 创建时必须要有 BpublicA(Bb){this.b=b;}}@ServicepublicclassB{privatefinalAa;// 构造器注入:B 创建时必须要有 ApublicB(Aa){this.a=a;}}

结果:这是一个死锁。A 等 B 出生,B 等 A 出生。Spring 的三级缓存也救不了(因为对象还没实例化,没法放入缓存)。
解法:必须在其中一个构造参数上加@Lazy

2. 多例(Prototype)作用域的循环依赖
@Service@Scope("prototype")// 多例publicclassA{@AutowiredBb;}@Service@Scope("prototype")// 多例publicclassB{@AutowiredAa;}

结果:Spring 的三级缓存只支持单例 Bean 的循环依赖。对于多例,Spring 每次都要创建新对象,无法缓存“半成品”,所以直接报错。
解法:@Lazy

3. 自己注入自己(自调用)
@ServicepublicclassUserService{@AutowiredprivateUserServiceuserService;// 自己注入自己}

结果:这本质上也是一种循环依赖。如果不加@Lazy,Spring 会陷入无限递归创建中。
解法:必须加@Lazy


📊 总结对照表

场景是否构成循环依赖?不加@Lazy会怎样?备注
普通单向依赖(A->B)正常启动绝大多数项目的常态
单例 + 字段注入(A<->B)通常能启动Spring 三级缓存自动解决(但在 Boot 2.6+ 需配置允许)
构造器注入(A<->B)启动报错必须加@Lazy破局
多例 Bean(A<->B)启动报错必须加@Lazy破局
自注入(A->A)启动报错必须加@Lazy破局

所以,只有当你确实遇到了上述几种“死锁”情况,或者你想优化启动性能(延迟加载重量级 Bean)时,才需要考虑@Lazy

http://www.cnnetsun.cn/news/2103656.html

相关文章:

  • 【OpenClaw从入门到精通】第70篇:为什么它是LLM落地的“最后一公里”?(2026全场景实操指南)
  • 用户昵称 2023-12-01 10:30:00
  • ITK-SNAP医学图像分割:从新手到专家的完整实战指南
  • NumPy数组广播机制详解与应用实践
  • 古代百姓真的能吃饱饭吗?历史真相下的底层百姓生活真相
  • 别再手动调电阻了!AD8226搭配AD5293,打造一个可编程增益放大器(PGA)的完整方案与避坑指南
  • 实时音频处理终极指南:如何用Stream-Translator实现流媒体翻译
  • MCP 2026调度引擎重构全记录(仅限首批认证架构师内部解密)
  • 【无人机三维路径规划】改进灰狼算法I-GWO多策略融合的无人机UAV路径规划【含Matlab源码 15377期】
  • 基于MCP协议的智能代码助手:架构解析与本地部署实践
  • 专精特新中小企业基本信息库2024
  • 打卡信奥刷题(3170)用C++实现信奥题 P7915 [CSP-S 2021] 回文
  • 从STM32转战GD32?KEIL工程迁移避坑指南(以F103C8T6为例,解决启动文件、宏定义差异)
  • 校园资讯平台系统|基于java和小程序的校园资讯平台设计与实现(源码+数据库+文档)
  • 废物利用指南:把移动融合终端H10G-13AC刷成电视盒子+轻NAS(晶晨S905L3S通刷包实战)
  • 如何快速配置象棋AI:深度学习辅助的完整指南
  • 5分钟掌握EB Garamond 12:免费商用复古字体终极指南
  • 终极编程语言图标资源库:告别技术文档的视觉混乱时代
  • flutter
  • qmc-decoder终极指南:如何快速解锁QQ音乐加密音频文件?
  • 怎样高效解密网易云NCM音乐文件:ncmdumpGUI完全实用指南
  • 布隆过滤器(Bloom Filter)技术详解
  • eternal_silence
  • 基于向量数据库与强化学习的智能体框架开发实战
  • 自动驾驶算法岗必备:手把手教你优化C++角度归一化代码(从Apollo源码说起)
  • AI模型调试总“污染”宿主机?手把手配置Docker Sandbox实现进程/网络/文件系统三重隔离(含strace验证脚本)
  • 终极解密:MS-DOS源代码如何塑造现代操作系统架构
  • MCP 2026量子计算节点对接全链路解析(从经典控制面握手到量子态保真度校验的11层协议穿透)
  • 3000+免费科研矢量图标库:Bioicons如何彻底改变你的科学可视化工作流?
  • AdaBoost算法原理与实践:从基础到优化