当前位置: 首页 > news >正文

设计教程网站推荐网站开发 质量管理

设计教程网站推荐,网站开发 质量管理,有什么网站开发软件,建电子商务网站需要多少钱Spring循环依赖:原理、问题与解决方案一、循环依赖的定义在Spring框架中,循环依赖是指两个或多个Bean之间相互依赖,形成一个闭环的情况。例如,BeanA依赖于BeanB,同时BeanB又依赖于BeanA。这种情况在通过setter方法注入…

Spring循环依赖:原理、问题与解决方案

一、循环依赖的定义

在Spring框架中,循环依赖是指两个或多个Bean之间相互依赖,形成一个闭环的情况。例如,BeanA依赖于BeanB,同时BeanB又依赖于BeanA。这种情况在通过setter方法注入或者@Autowired属性注入时较为常见。

代码示例

// BeanA类
public class BeanA {private BeanB beanB;//  setter方法注入BeanBpublic void setBeanB(BeanB beanB) {this.beanB = beanB;}
}// BeanB类
public class BeanB {private BeanA beanA;//  setter方法注入BeanApublic void setBeanA(BeanA beanA) {this.beanA = beanA;}
}

二、Spring三级缓存机制

(一)缓存结构

  1. ​一级缓存​

    • 作用:存放完全初始化好的Bean实例。

    • 存储类型:ConcurrentHashMap类型的SingletonObjects

    • 意义:当需要获取一个已经完全初始化的Bean时,可以直接从一级缓存中获取,提高获取Bean的效率。

  2. ​二级缓存​

    • 作用:存放未完成属性注入的Bean实例。

    • 存储类型:HashMap类型的earlySingletonObjects

    • 意义:在Bean实例创建过程中,当实例已经创建但还未完成属性注入等操作时,先将这个“半成品”的Bean实例存放在二级缓存中,以应对可能出现的其他Bean对它的依赖。

  3. ​三级缓存​

    • 作用:存放Bean的ObjectFactory

    • 存储类型:HashMap类型的singletonFactories

    • 意义:ObjectFactory是一个用于懒加载Bean的接口,它可以在需要时提供Bean的实例,而不是立即创建和存储它。这一机制有助于解决setter方法和@Autowired属性注入的循环依赖问题。

(二)Bean创建流程与三级缓存的关系

  1. 当创建一个Bean(例如BeanA)时,首先会将BeanA的ObjectFactory放入三级缓存。

  2. 在BeanA实例创建完成后,会进行属性注入。如果在注入属性时发现需要BeanB,那么就会开始创建BeanB。

  3. 同样,创建BeanB时,也会将BeanB的ObjectFactory放入三级缓存。

  4. 在注入BeanB的属性时,如果发现需要BeanA,此时就可以从三级缓存中获取到BeanA的ObjectFactory,并通过它来获取BeanA的实例(这个实例可能是还未完全初始化的),然后将这个实例注入到BeanB中,之后再将这个实例放入二级缓存,继续完成BeanB的其他初始化操作。最后,将完全初始化后的BeanB实例放入一级缓存,再将BeanB注入到BeanA中,从而完成BeanA的初始化。

三、构造器注入的循环依赖问题

(一)问题产生的原因

  1. 三级缓存机制只有在对象实例已经创建(即构造方法执行完后)才能生效,从而将实例暴露到earlySingletonObjects中。

  2. 在使用构造器注入时,Spring必须先创建依赖对象才能调用构造器。例如,BeanA的构造器必须要BeanB的实例作为参数,而BeanB又等着BeanA的实例,这就导致Spring在创建BeanA时,由于需要BeanB的实例,但BeanB的创建又依赖于BeanA的实例,使得Spring根本无法创建任何一个Bean的实例,从而导致了死锁。

(二)解决方案:@Lazy注解

  1. ​原理​

    • 可以通过在构造器中对参数添加@Lazy注解,让Spring注入一个代理对象。这个代理对象并不会立即触发依赖Bean的真正初始化,而是在真正调用该依赖Bean的方法时才会触发其初始化。

  2. ​示例代码修改​

    • 对于BeanA的构造器进行修改:

    public class BeanA {private BeanB beanB;// 使用@Lazy注解@Autowiredpublic BeanA(@Lazy BeanB beanB) {this.beanB = beanB;}
    }

四、其他相关问题与最佳实践

(一)其他解决方案探讨

  1. ​@PostConstruct注解​

    • 虽然不能直接解决构造器注入的循环依赖问题,但可以在Bean的初始化阶段进行一些操作,例如在@PostConstruct注解标注的方法中进行一些属性的设置或者资源的加载,这些操作可以在依赖注入完成之后进行。

  2. ​使用setter注入​

    • 在可能的情况下,推荐使用setter注入而非构造器注入。因为setter注入不会在实例创建时就需要依赖的Bean,而是在Bean实例创建完成后再进行属性注入,这样可以避免构造器注入带来的循环依赖问题。

(二)Bean作用域对循环依赖的影响

  1. 对于prototype作用域的Bean,由于其每次获取时都会创建新的实例,所以在处理循环依赖时相对复杂。如果出现循环依赖,可能会导致更多的问题,因为无法像单例Bean那样可以通过缓存机制来解决。

(三)最佳实践总结

  1. 在设计Bean之间的依赖关系时,尽量避免循环依赖的出现。如果无法避免,优先考虑使用setter注入或者字段注入(通过@Autowired)的方式。

  2. 如果必须使用构造器注入且出现了循环依赖问题,可以考虑使用@Lazy注解来解决。

  3. 在使用@PostConstruct注解时,要确保其标注的方法中的操作不会引入新的循环依赖或者影响Bean的正常初始化顺序。

http://www.dtcms.com/a/504403.html

相关文章:

  • 阆中网站网站建设郴州网站建设公司哪个好
  • 【STM32笔记】:P04 断言的使用
  • 阿里巴巴建网站龙华网站建设专业公司
  • 新手学wordpress优化落实防控措施
  • 基于彩色线图像增强和改进型YOLOv7模型的海洋水产养殖生物体检测
  • 网站可以免费建立吗网络游戏企业不得向提供游戏服务
  • codetop高频(3)
  • 兰州网络推广关键词优化网站营销seo
  • 开发大型网站的流程wordpress自定义搜索
  • 站长 网站ip怒江商城网站建设
  • 商丘网站建设专业现状wordpress网页版入口
  • QDarkStyleSheet: 一个Qt应用的暗色主题解决方案
  • 各种网站app长沙人才市场招聘
  • 从零开始的C++学习生活 10:继承和多态
  • 记事本怎么做网站一人办厂千元投资
  • Java代码之gradle(1)
  • 卖印花图案设计网站网站建设实验小结
  • 织梦网站如何做seowordpress类
  • C# 数据加载专题 之泛型序列化
  • 帮网站做代理青岛网页设计 学校
  • 【2026计算机毕业设计】基于Springboot的校园电动车短租平台
  • Java基础语法—输入输出
  • 南京网站建设培训wordpress免费下主题Modown
  • 临时邮箱系统实战:解决AI网站注册验证难题的技术方案
  • K8s 安全机制全解析
  • 备案的网站名称湖南众诚建设 官方网站
  • 从0死磕全栈之使用 VS Code 调试 Next.js 应用完整指南
  • 换空间对网站排名的影响吗信息技术做网站
  • 做网站赚钱流程松江集团网站建设
  • NVIDIA大模型推理框架:TensorRT-LLM软件流程(一)