Spring循环依赖-博客园
1. 什么是循环依赖
2. 循环依赖能引发什么题目
循环依赖可能引发以下题目:
- 初始化顺序不确定:循环依赖导致无法确定哪个对象应该先被创建和初始化,从而造成初始化顺序的杂乱。这可能导致错误的结果或意外的行为。
- 死锁和无限递归:当循环依赖中的对象在创建过程中相互等待对方完成创建时,可能会导致死锁或无限递归的环境发生。这将使程序无法继续实行,终极导致系统崩溃或进入无限循环。
- 难以明白和维护:循环依赖增加了代码的复杂性和耦合度,使得代码难以明白和维护。在一个循环依赖链中,修改一个类可能会影响到其他所有相干的类,增加了代码的脆弱性。
- 可测试性降落:循环依赖使得各个模块或类之间的责任不清晰,难以进行单独的单元测试或模块拆解。这给软件的测试和调试带来困难,低落了可测试性和可维护性。
3. Spring是怎么处理循环依赖的
为克制循环依赖带来的题目,应只管克制在计划和实现中出现循环依赖关系。重新考虑系统的架构,采用符合的计划模式、解耦方式和依赖注入机制,可以帮助办理或克制循环依赖带来的题目。
据此我们得到以下结论:
spring容器中原型(Prototype)的场景是不支持循环依赖的,抛出BeanCurrentlyInCreationException非常
其实,Spring容器中单例(singleton)的场景是支持循环依赖的,Spring利用了三级缓存和提前曝光(early exposure)的机制来处理循环依赖题目
- 第一级缓存(也叫单例池)singletonObjects:存放已经履历了完整生命周期的Bean对象
- 第二级缓存: earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整)
- 第三级缓存: Map<String, ObiectFactory<?>> singletonFactories,存放可以天生Bean的工厂
所谓的三级缓存其实就是spring容器内部用来办理循环依赖题目的三个map
Spring实例Bean的本质
- 实例化
- 堆内存中申请一块内存空间
- 租赁好房子,自己的家具东西还没有搬家进去
- 初始化属性填充
3大Map和四大方法,总体相干对象
1.getSingleton:从容器内里得到单例的bean
2.doCreateBean: 没有就创建bean
3.populateBean: 创建完了以后,要填充属性
4.addSingleton: 填充完了以后,再添加到容器进行利用
第一层singletonObjects存放的是已经初始化好了的Bean,
第二层earlySingletonObjects存放的是实例化了,但是未初始化的Bean,
第三层singletonFactories存放的是FactoryBean。假如A类实现了FactoryBean,那么依赖注入的时候不是A类,而是A类产生的Bean
A/B两对象在三级缓存中的迁移说明
- A创建过程中需要B,于是A将自己放到三级缓存内里,去实例化B
- B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存内里的这个A放到二级缓存内里,并删除三级缓存内里的A
- B顺遂初始化完毕,将自己放到一级缓存内里(此时B内里的A依然是创建中状态) 然后回来接着创建A,此时B已经创建结束,直接从一级缓存内里拿到B,然后完成创建,并将A自己放到一级缓存内里。
https://blog.csdn.net/weixin_41883161/article/details/139706538
Spring框架通过三级缓存(三级缓存机制)来办理大多数环境下的循环依赖题目。三级缓存机制包括以下三个层次:
- 单例池(singletonObjects):用于存放完全初始化好的单例Bean。
- 早期曝光对象池(earlySingletonObjects):用于存放部分初始化完成的单例Bean,通常是通过提前暴露Bean引用来办理循环依赖。
- 三级缓存(singletonFactories):用于存放Bean工厂,以便在需要时创建Bean实例。
- > 4.1 三级缓存机制详解
- > 4.1.1 单例池(singletonObjects) 单例池是一个Map,用于存放完全初始化好的单例Bean。当Spring容器创建一个Bean时,会首先检查单例池中是否已经存在该Bean,如果存在则直接返回,否则继续创建。
- >
- > 4.1.2 早期曝光对象池(earlySingletonObjects) 早期曝光对象池是一个Map,用于存放部分初始化完成的单例Bean。当Spring容器检测到循环依赖时,会将部分初始化完成的Bean提前放入该池中,以便其他Bean能够引用。
- >
- > 4.1.3 三级缓存(singletonFactories) 三级缓存是一个Map,用于存放Bean工厂。Bean工厂是一个用于创建Bean实例的对象,当需要创建Bean实例时,Spring容器会从三级缓存中获取相应的Bean工厂,并通过它来创建Bean实例。
复制代码 4.2 三级缓存的工作流程
- Spring容器创建Bean A,首先检查单例池中是否存在Bean A。
- 如果单例池中不存在Bean A,则检查早期曝光对象池中是否存在Bean A。
- 如果早期曝光对象池中也不存在Bean A,则从三级缓存中获取Bean A的工厂,并通过该工厂创建Bean A的实例。
- 创建Bean A实例的过程中,发现Bean A依赖于Bean B,因此开始创建Bean B。
- 创建Bean B的过程中,发现Bean B依赖于Bean A,此时检测到循环依赖。
- 将Bean A的实例放入早期曝光对象池中,以便Bean B可以引用。
- 继续完成Bean B的创建,并将其放入单例池中。
- 返回Bean B的实例,继续完成Bean A的创建,并将其放入单例池中。
- 通过上述流程,Spring容器可以成功处理大多数情况下的循环依赖。
复制代码 4. Spring怎样注入才气不产生循环依赖题目
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |