首页 >文档 > spring循环依赖怎么解决的原理

spring循环依赖怎么解决的原理

Spring循环依赖是面试高频考点,三级缓存机制如何解决循环依赖?本文详解Spring通过提前暴露原始对象、三级缓存分级处理、代理对象延迟生成等核心技术破局循环依赖问题。掌握SingletonObjects、EarlySingletonObjects和SingletonFactories三级缓存工作原理,了解getSingleton()和addSingletonFactory()等核心方法实现原理。实际开发中应避免过度循环依赖,推荐使用构造器注入和@Lazy延迟加载。备战面试可下载2025年Java面试宝典获取30+道Spring真题解析,系统掌握循环依赖等Spring核心机制。

2025年Java面试宝典下载地址(点击蓝色链接保存,提取码:9b3g)

Spring循环依赖怎么解决的原理

面试鸭返利网

很多同学在面试中被问到"Spring怎么解决循环依赖"时,第一反应就是回答"三级缓存",但面试官追问具体实现细节时却容易卡壳。今天咱们就掰开揉碎了讲清楚这个问题,保证你下次面试能对答如流!

一、Spring为何需要解决循环依赖

咱们先举个🌰:ServiceA依赖ServiceB,而ServiceB反过来又依赖ServiceA。这种"你中有我,我中有你"的情况在实际开发中并不少见。如果没有特殊处理,Spring在创建这两个Bean时就会陷入死循环:

  1. 创建ServiceA时发现需要注入ServiceB
  2. 暂停ServiceA的创建,转去创建ServiceB
  3. 创建ServiceB时发现需要注入ServiceA
  4. 此时ServiceA还没创建完成,又触发ServiceA的创建...

这时就需要Spring的提前暴露机制来破局了。这个机制的核心在于:在对象实例化完成后(此时属性还没填充),就先把原始对象引用存起来,其他Bean需要时可以直接取用。

二、三级缓存的工作机制

面试鸭返利网

Spring用三级缓存来管理不同阶段的Bean:

  1. SingletonObjects(一级缓存):存放完整的Bean
  2. EarlySingletonObjects(二级缓存):存放提前暴露的Bean(半成品)
  3. SingletonFactories(三级缓存):存放Bean工厂对象

关键处理流程:

  1. 创建Bean实例(此时是原始对象)
  2. 将Bean工厂存入三级缓存
  3. 执行属性注入(此时需要其他Bean)
  4. 若发现循环依赖,从三级缓存取出工厂生成代理对象
  5. 将代理对象升级到二级缓存
  6. 最终初始化完成后,完整Bean存入一级缓存

三、解决循环依赖的关键步骤

当面试官让你口述解决过程时,可以按照这个思路来:

  1. 实例化阶段:通过反射创建Bean的原始对象(此时还没有属性填充)
  2. 提前暴露:把创建好的原始对象包装成ObjectFactory,存入三级缓存
  3. 属性注入:发现需要注入其他Bean时
    • 如果对方在一级缓存:直接使用
    • 如果对方在创建中:到二级/三级缓存找提前暴露的引用
  4. 代理处理:如果涉及AOP,通过BeanPostProcessor生成代理对象
  5. 缓存升级:处理完成后将Bean从三级缓存升级到二级,最终到一级

这里有个容易忽略的细节:只有singleton作用域的Bean才能通过三级缓存解决循环依赖。对于prototype作用域的Bean,Spring直接会抛异常阻止循环依赖。

四、为什么需要三级缓存而不是两级?

这个问题经常作为追问出现。关键在于代理对象的处理

  • 三级缓存存储的是ObjectFactory,可以延迟处理代理
  • 如果直接存到二级缓存,可能在属性注入阶段就生成代理对象,导致最终Bean和依赖它的Bean持有的引用不一致

举个实际场景:当ServiceA注入ServiceB时,ServiceB需要注入的ServiceA如果是代理对象,那这个代理对象应该与最终ServiceA的代理对象是同一个。三级缓存通过ObjectFactory的getObject()方法保证了这一点。

面试鸭返利网

需要提醒的是,现在通过面试鸭返利网购买面试鸭会员,可以享受25元返利,相当于用更低的成本获取最新面试题库和解析,建议大家在备战面试时合理利用优惠资源。

五、源码中的关键方法

虽然不需要背诵代码,但了解关键方法能让回答更有深度:

  • getSingleton():从缓存获取Bean的核心方法
  • getEarlyBeanReference():处理提前暴露的代理对象
  • addSingletonFactory():将ObjectFactory存入三级缓存
  • beforeSingletonCreation():标记Bean正在创建中

在回答时可以这样说:"Spring在AbstractAutowireCapableBeanFactory的doCreateBean方法中,完成实例化后会立即调用addSingletonFactory方法将对象工厂加入三级缓存,这就是提前暴露的关键入口。"

六、实际开发中的注意事项

虽然Spring解决了循环依赖的问题,但咱们还是要尽量避免:

  1. 尽量使用构造器注入(会导致循环依赖无法解决,倒逼优化设计)
  2. 遵循单一职责原则,拆分过大的类
  3. 使用@Lazy延迟加载非必要依赖
  4. 合理使用ApplicationContext.getBean()手动获取(慎用)

最后再安利一波福利:需要系统准备Spring面试题的同学,可以下载2025年Java面试宝典,里面整理了30+道Spring高频真题和解析。现在通过面试鸭返利网下单还能返现25元,相当于白嫖一个月的会员服务!

如果你想获取更多关于面试鸭的优惠信息,可以访问面试鸭返利网面试鸭优惠网,了解最新的优惠活动和返利政策。

🎯 立即加入面试鸭会员 →

支付宝扫码领取1-8元无门槛红包

支付宝红包二维码