面试官:详细介绍一下Spring的循环依赖

💡 原文中文,约5800字,阅读约需14分钟。
📝

内容提要

Spring的循环依赖问题可以通过三级缓存来处理,避免循环依赖。一级和二级缓存无法处理循环依赖,三级缓存可以处理普通Bean的循环依赖,但对于代理Bean的循环依赖仍然存在问题。构造器注入的类无法处理循环依赖,但可以通过@Lazy注解推迟加载解决。

🔎

延伸解读

三级缓存如何解决循环依赖

Spring通过三级缓存提前暴露Bean的早期引用,避免循环依赖。实例化后,Bean会被放入三级缓存(SingletonFactory),当其他Bean需要注入时,可以从缓存中获取早期引用,而无需重新创建Bean。这打破了循环依赖的死循环。

为什么需要三级缓存而非二级

二级缓存可以处理普通Bean的循环依赖,但对于代理Bean(如AOP代理)则存在问题。因为代理对象的创建通常发生在初始化阶段,如果提前创建代理,可能缺少原始Bean的属性。三级缓存通过FactoryBean延迟代理对象的创建,仅在发生循环依赖时生成代理,符合Spring AOP的设计原则。

循环依赖的局限性

Spring的三级缓存只能解决单例Bean的循环依赖,原型(prototype)作用域的Bean无法处理,因为每次都会创建新实例,不进入缓存。此外,构造器注入的循环依赖也无法解决,因为实例化未完成时就需要依赖对象。但可以通过@Lazy注解推迟加载,从而避免循环依赖。

❓

Q&A

什么是Spring的循环依赖?

Spring的循环依赖是指两个Bean相互依赖,导致死循环的现象。

Spring如何处理循环依赖?

Spring通过三级缓存来处理循环依赖,一级和二级缓存无法解决此问题。

三级缓存的组成部分是什么?

三级缓存包括一级缓存(存储完整Bean)、二级缓存(存储半成品Bean)和三级缓存(存储FactoryBean)。

为什么一级和二级缓存无法处理循环依赖?

一级缓存无法处理循环依赖因为依赖注入发生在初始化之前,二级缓存对代理Bean处理复杂。

构造器注入的类如何解决循环依赖问题?

构造器注入的类无法处理循环依赖,但可以通过@Lazy注解推迟加载来解决。

三级缓存只支持单例Bean吗?

是的,三级缓存只支持单例Bean,原型Bean无法处理循环依赖。

🏷️

标签

➡️

继续阅读