大家好,我是小米,今天我们来聊聊 Spring 框架中的一个重要话题:循环依赖。在开发中,我们可能会遇到这样的问题:两个或多个 bean 之间相互依赖,导致创建对象时出现死循环。那么,Spring 是如何解决这个问题的呢?
【资料图】
在 Spring 中,bean 之间的依赖关系可以通过构造函数注入、Setter 注入、接口注入等方式实现。当两个或多个 bean 相互依赖时,就会形成循环依赖。比如,bean A 依赖于 bean B,而 bean B又依赖于 bean A,这就是循环依赖。
Spring使用“三级缓存”来解决循环依赖的问题。三级缓存指的是singletonObjects、earlySingletonObjects和singletonFactories三个Map。
在Spring创建对象时,会先检查 singletonObjects 中是否已经存在该对象的实例,如果存在,则直接返回该实例;如果不存在,则检查 earlySingletonObjects 中是否已经存在该对象的“提前曝光”的代理对象,如果存在,则返回该代理对象,否则就调用singletonFactories 中存储的工厂方法来创建该对象的实例,并将其放入 earlySingletonObjects 中,同时存储一个 Factory 对象到singletonFactories 中。
当对象创建完成之后,就会从 earlySingletonObjects中 移除该对象的代理对象,将完整的对象实例放入 singletonObjects 中,并清空 singletonFactories中的Factory 对象。这样,下次获取该对象的实例时,就可以直接从 singletonObjects 中获取了。
当出现循环依赖时,Spring 会将正在创建的对象提前曝光,也就是将一个代理对象放到 earlySingletonObjects 中,然后在创建对象时,将代理对象注入到另一个需要依赖该对象的 bean 中。这样,当需要使用该对象时,就可以从 earlySingletonObjects 中获取到代理对象,避免了死循环的出现。
三级缓存可以保证对象的单例性,同时也可以解决循环依赖的问题。而单例对象的创建和获取是很频繁的操作,所以使用三级缓存可以提高效率。
三级缓存:当 Spring 创建一个bean的实例时,会将其放入singletonFactories中,这个操作是在createBeanInstance之后完成的。同时,也会将该 bean 的工厂方法放入singletonFactories中。这样,当需要获取该 bean 的实例时,就可以从 singletonFactories 中获取到其对应的工厂方法。
二级缓存:当 Spring 从 singletonFactories 中获取到一个bean 的工厂方法后,会通过该工厂方法创建该 bean 的实例,并将其放入 earlySingletonObjects 中。同时,也会将其代理对象放入 earlySingletonObjects 中。
在后续创建依赖该 bean 的其他 bean 时,如果需要获取该bean 的实例,就会从 earlySingletonObjects 中获取到其代理对象。在第一次从 earlySingletonObjects 中获取到该代理对象时,Spring 会判断该对象是代理对象还是普通对象,如果是代理对象,则会将其替换为其对应的普通对象,并从 earlySingletonObjects 中删除该代理对象。
一级缓存:当Spring创建完一个bean的完整实例后,会将其放入 singletonObjects 中,并从 earlySingletonObjects中删除其对应的代理对象和工厂方法。同时,也会将其对应的bean的依赖项从 dependencyCheck 中移除。这样,下次获取该bean的实例时,就可以直接从 singletonObjects 中获取了。
除了三级缓存之外,提前曝光是 Spring 解决循环依赖问题的重要手段之一。当 Spring 创建一个 bean 的实例时,如果检测到其依赖了另一个正在创建的 bean,则会将其提前曝光,即将一个代理对象放入 earlySingletonObjects 中,以便在后续创建依赖该 bean 的其他 bean 时,可以直接使用其代理对象,避免了死循环的出现。不过,提前曝光的方法需要手动配置,比较麻烦,所以一般情况下,我们都会使用 Spring 提供的三级缓存来解决循环依赖的问题。
总的来说,Spring 是一个非常优秀的 Java 框架,它不仅提供了依赖注入和 AOP 等常用功能,还能够很好地解决循环依赖的问题。而这些都离不开 Spring 框架底层的设计和实现。希望今天的分享能够帮助大家更好地理解 Spring 框架的原理和实现,也希望大家能够继续深入学习和研究 Java 技术,不断提升自己的能力。谢谢大家的阅读!
如有疑问或者更多的技术分享,欢迎关注我的微信公众号“知其然亦知其所以然”!
1、葛友元,于12月7日出生于江苏省徐州市,祖籍江苏苏州。[1] 中国内地演员, 武昌理工学院客座教授 ,
该系列有GTR7及GTR7Pro两款,分别搭配锐龙77840HS、锐龙97940HS处理器,都是8核16线程Zen4架构CPU,12组CU
看照片软件官方下载,看照片软件这个很多人还不知道,现在让我们一起来看看吧!1、如果你是WINDOWSX
21世纪经济报道记者缴翼飞北京报道时隔三个月,制造业采购经理指数(PMI)再次回落至荣枯线以下。4月30日,
1日季后赛前瞻:勇士抢七力争会师湖人巴特勒G1能否延续神奇?,勇士,湖人,热火队,雄鹿队,美国篮球,巴特勒g1,
X 关闭
X 关闭
国内首个“云保险鱼塘”长啥样?近日,记者实地进行了探访。在广东省肇庆市四会市国斌水产养殖合作社,记者见到了合作社带头人马国斌。刚刚[+更多]
背景介绍作为应用最广泛的包装用品之一,纸箱承担着容装、保护产品、美观的重要责任。其市场需求也随着国内消费、物流运输及出口包装行业的[+更多]
【资料图】ABB高压电机有限公司研发中心作为ABB电机业务全球研发的重要组成部分,从建成伊始起,就始终致力于“在中国,为中国和世界”作为[+更多]
近日,深圳市国家级专精特新"小巨人"企业名单公布,正弦电气成功入选国家级专精特新"小巨人"企业名单。S I N E E专精特新“小巨人”专[+更多]