Spring 办理bean的循环依赖

打印 上一主题 下一主题

主题 1517|帖子 1517|积分 4551

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实例。
  1. > 4.1 三级缓存机制详解
  2. > 4.1.1 单例池(singletonObjects) 单例池是一个Map,用于存放完全初始化好的单例Bean。当Spring容器创建一个Bean时,会首先检查单例池中是否已经存在该Bean,如果存在则直接返回,否则继续创建。
  3. >
  4. > 4.1.2 早期曝光对象池(earlySingletonObjects) 早期曝光对象池是一个Map,用于存放部分初始化完成的单例Bean。当Spring容器检测到循环依赖时,会将部分初始化完成的Bean提前放入该池中,以便其他Bean能够引用。
  5. >
  6. > 4.1.3 三级缓存(singletonFactories) 三级缓存是一个Map,用于存放Bean工厂。Bean工厂是一个用于创建Bean实例的对象,当需要创建Bean实例时,Spring容器会从三级缓存中获取相应的Bean工厂,并通过它来创建Bean实例。
复制代码
4.2 三级缓存的工作流程
  1. Spring容器创建Bean A,首先检查单例池中是否存在Bean A。
  2. 如果单例池中不存在Bean A,则检查早期曝光对象池中是否存在Bean A。
  3. 如果早期曝光对象池中也不存在Bean A,则从三级缓存中获取Bean A的工厂,并通过该工厂创建Bean A的实例。
  4. 创建Bean A实例的过程中,发现Bean A依赖于Bean B,因此开始创建Bean B。
  5. 创建Bean B的过程中,发现Bean B依赖于Bean A,此时检测到循环依赖。
  6. 将Bean A的实例放入早期曝光对象池中,以便Bean B可以引用。
  7. 继续完成Bean B的创建,并将其放入单例池中。
  8. 返回Bean B的实例,继续完成Bean A的创建,并将其放入单例池中。
  9. 通过上述流程,Spring容器可以成功处理大多数情况下的循环依赖。
复制代码
4. Spring怎样注入才气不产生循环依赖题目


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

八卦阵

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表