Spring循环依赖详解

Spring通过三级缓存解决单例Bean的循环依赖(属性注入),但构造器注入和原型Bean无法处理,需避免或使用@Lazy延迟加载。


Spring循环依赖详解

1. 循环依赖的产生场景

当两个或多个Bean相互直接或间接依赖,形成闭环时,触发循环依赖。例如:

  • Bean A → Bean B → Bean A
  • Bean A → Bean B → Bean C → Bean A

2. Spring的解决机制(单例模式)

通过 三级缓存 提前暴露未初始化的Bean引用:

  1. singletonObjects:缓存完全初始化的Bean。
  2. earlySingletonObjects:缓存提前暴露的原始Bean(未完成属性注入)。
  3. singletonFactories:缓存Bean的ObjectFactory(用于生成早期代理对象)。

解决流程示例(A → B → A)

  1. 实例化A(调用构造函数),将A的ObjectFactory放入三级缓存。
  2. 填充A的属性时发现依赖B,触发B的实例化。
  3. 实例化B,填充属性时发现依赖A,从三级缓存获取A的早期引用并注入。
  4. B完成初始化后放入一级缓存,A继续完成属性注入和初始化。

3. 无法解决的场景

  • 构造器注入循环依赖 : 构造函数需在实例化时完成所有依赖注入,无法提前暴露引用,抛出BeanCurrentlyInCreationException
  • 原型(Prototype)Bean的循环依赖: Spring不缓存原型Bean,每次请求生成新实例,无法通过三级缓存解决。

4. 解决方案

  • 代码重构:引入中间层或接口解耦。

  • 使用Setter/字段注入:替代构造器注入。

  • @Lazy延迟加载:对依赖生成代理,延迟初始化。

    less 复制代码
    @Component
    public class ServiceA {
        @Lazy
        @Autowired
        private ServiceB serviceB;
    }
  • 调整Bean初始化顺序 :通过@DependsOn强制指定顺序。

5. 源码关键逻辑

  • 提前暴露引用AbstractAutowireCapableBeanFactory.doCreateBean()中调用addSingletonFactory
  • 依赖解析DefaultSingletonBeanRegistry.getSingleton()从缓存中查找Bean。

6. 最佳实践

  • 优先使用Setter注入:避免构造器循环依赖。
  • 避免过度依赖:通过模块化设计减少直接依赖。
  • 监控与日志 :启用-Dspring.main.allow-circular-references=true(Spring Boot 2.6+默认禁用循环依赖)。

总结:Spring通过三级缓存解决单例属性注入的循环依赖,但需避免构造器注入和原型作用域的循环场景,合理使用@Lazy和设计模式降低耦合。

相关推荐
码云数智-园园12 小时前
C++20 Modules 模块详解
java·开发语言·spring
咖啡八杯13 小时前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
Flittly13 小时前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring
李少兄13 小时前
从原理到实战:Spring IoC/DI 核心知识体系与高频面试题全解
java·后端·spring
shushangyun_14 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
ofoxcoding14 小时前
在AI API聚合平台配置DeepSeek V3.2提示词缓存实战:快速接入与成本优化指南
人工智能·spring·缓存·ai
一杯奶茶¥16 小时前
水果销售网站 CRM客户信息管理系统 超市管理系 酒店管理系统 健身房管理系统 在线音乐网站 校园招聘系统
java·vue.js·spring boot·mysql·spring·java项目
摇滚侠18 小时前
SpringMVC 入门到实战 RESTFul 49-55
java·开发语言·后端·spring·intellij-idea·restful
我登哥MVP18 小时前
SpringCloud Alibaba 核心组件解析:服务链路追踪
java·spring boot·后端·spring·spring cloud·java-ee·maven
Ysouy18 小时前
Spring Data Elasticsearch 全流程学习教程
java·spring·elasticsearch