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

红花岗区建设局网站淄博乐达信息技术网站

红花岗区建设局网站,淄博乐达信息技术网站,线上推广引流,wordpress 打开慢方法一、什么是循环依赖? 循环依赖(Circular Dependency) 指两个或多个 Bean 之间相互依赖,导致在创建 Bean 的过程中出现“死循环”,增加了对象依赖的混乱性,依赖关系变得错综复杂。 常见三种类型的循环依赖…

一、什么是循环依赖?

循环依赖(Circular Dependency) 指两个或多个 Bean 之间相互依赖,导致在创建 Bean 的过程中出现“死循环”,增加了对象依赖的混乱性,依赖关系变得错综复杂。

常见三种类型的循环依赖:

类型举例Spring 是否能解决
构造器注入循环依赖A → B → A(构造方法注入)
Setter / 字段注入循环依赖A → B → A(@Autowired)
Prototype 范围循环依赖A(原型) → B(原型) → A

1. 构造器注入循环依赖(Spring ❌无法解决)

@Component
public class A {private final B b;@Autowiredpublic A(B b) {this.b = b;}
}@Component
public class B {private final A a;@Autowiredpublic B(A a) {this.a = a;}
}

❌ 结果:

报错:BeanCurrentlyInCreationException: Requested bean is currently in creation: Is there an unresolvable circular reference?

  • 原因:Spring 必须先构造 A 才能注入 B,但 B 的构造又依赖 A,导致死循环,无法通过三级缓存提前暴露 Bean

2. 字段(或 setter)注入循环依赖(Spring ✅能自动解决)

@Component
public class A {@Autowiredprivate B b;
}@Component
public class B {@Autowiredprivate A a;
}

✅ 结果:

Spring 能自动解决,应用成功启动。

  • 原因:Spring 会先构造出一个“空的 A 实例”,将其工厂加入三级缓存,B 注入 A 时就能拿到早期引用,从而打破循环。

  • 前提:spring.main.allow-circular-references: true,必须开启情况下才能自动解决。然Spring 6.0 起(包括 Spring Boot 3.x)默认为false

3. 原型作用域的循环依赖(Spring ❌无法解决)

@Component
@Scope("prototype")
public class A {@Autowiredprivate B b;
}@Component
@Scope("prototype")
public class B {@Autowiredprivate A a;
}

❌ 结果:

报错:BeanCurrentlyInCreationException(创建过程中找不到可注入的 Bean)

  • 原因:Spring 不缓存 prototype Bean 的创建过程,无法通过三级缓存解决依赖链,原型 Bean 不参与依赖管理

二、Spring 如何解决循环依赖(基于单例 Bean)

Spring 采用一种经典的 三级缓存机制(3-level cache) 来解决循环依赖。这个机制存在于DefaultSingletonBeanRegistry中。

🚨 前提:仅对 @Scope("singleton") 且使用字段或 setter 注入有效!


1. Bean 创建流程概览(以 A → B → A 为例)

✅ Step-by-step:

  1. 创建 A 实例(构造函数执行);

  2. A被标记为“正在创建”,并将一个工厂(ObjectFactory)放入三级缓存

  3. A 依赖 B → Spring 创建 B;

  4. B 构造完成,发现依赖 A → 尝试获取 A;

  5. Spring 发现 A 正在创建 → 从三级缓存拿到 ObjectFactory 生成早期 A 对象 → 放入二级缓存

  6. B 成功注入 A,初始化完成;

  7. 回到 A,完成初始化。

整个过程中 Spring 使用缓存提前暴露未完成的 A 实例,从而打破了循环。

2. 三级缓存详解

缓存层级名称描述作用
一级缓存singletonObjects完全初始化完成的 Bean最终返回 Bean 实例
二级缓存earlySingletonObjects早期曝光的 Bean 实例用于依赖注入
三级缓存singletonFactories创建早期 Bean 的工厂延迟暴露 Bean 引用,支持代理等
Spring 将 Bean 提前曝光的流程:
singletonFactories -> earlySingletonObjects -> singletonObjects

3. 核心方法说明(来自源码)

在 Spring 源码中,关键方法如下:

// DefaultSingletonBeanRegistry.java// 一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();// 二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>();// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
  • 在创建 Bean 前:Spring 把一个生成 Bean 的工厂方法放入三级缓存。

  • 在注入依赖时:发现依赖的是一个“正在创建”的 Bean,就会去三级缓存中拿工厂生产早期对象。

  • 最后再完成依赖注入,放入一级缓存,清除早期引用。

三、业务开发者解决循环依赖的方法

1、使用@Lazy懒加载依赖

使用`@Lazy`注解延迟注入依赖属性。

@Component
public class A {@Autowired@Lazyprivate B b;
}

2、将依赖的代码移入新类,打破依赖闭环。

A → MiddleService → B

3、在方法中动态调用spring容器的getBean方法获取依赖,达到延迟获取bean,避免类中直接注入循环依赖的bean

使用 ObjectFactory 或 ApplicationContext.getBean() 延迟获取 Bean

@Component
@Scope("prototype")
public class A {@Autowiredprivate ObjectFactory<B> bFactory;public void use() {B b = bFactory.getObject(); // 延迟获取}
}

4、改为 setter 或字段注入(避免构造器注入)

构造器注入是“强依赖”,无法提前暴露:

@Component
public class A {private B b;@Autowiredpublic void setB(B b) {this.b = b;}
}

5、使用@PostConstruct 或 工厂方法延迟注入

将依赖注入放到初始化之后:

@Component
public class A {private final B b;public A(B b) {this.b = b;}@PostConstructpublic void init() {// 在这里安全使用 b}
}

6、开启Spring Boot循环依赖(不推荐,除非必要)。

spring:main:allow-circular-references: true


文章转载自:

http://8nDykrpr.myrmm.cn
http://BA7gbvkQ.myrmm.cn
http://gtoGArCF.myrmm.cn
http://KUXsjsRT.myrmm.cn
http://IjfjwMLY.myrmm.cn
http://h75nI9LE.myrmm.cn
http://yD1S4hiO.myrmm.cn
http://U0H9nDkk.myrmm.cn
http://ojQfomrT.myrmm.cn
http://fG3dyF05.myrmm.cn
http://TPvaqorm.myrmm.cn
http://WFKomwwT.myrmm.cn
http://5ulTVMFx.myrmm.cn
http://vgHus3G8.myrmm.cn
http://QAaGNlwP.myrmm.cn
http://ar8BfBWF.myrmm.cn
http://gxky6EaO.myrmm.cn
http://hO4Lkhan.myrmm.cn
http://av9qryOe.myrmm.cn
http://W9h3FT3w.myrmm.cn
http://ErTOhycg.myrmm.cn
http://7HNssZPg.myrmm.cn
http://RtBM7Hit.myrmm.cn
http://6PDjLdHr.myrmm.cn
http://Elacms7n.myrmm.cn
http://bGHl43K1.myrmm.cn
http://bFvUCQkt.myrmm.cn
http://K7D5fhkG.myrmm.cn
http://C3HkkRfC.myrmm.cn
http://9SEIOovC.myrmm.cn
http://www.dtcms.com/wzjs/605822.html

相关文章:

  • 网站版面设计说明韩国 网站 域名
  • 淄博建站哪家好知乎seo排名帝搜软件
  • 网站关于我们怎么做单页面域名注册免费申请
  • 常州地区做网站最权威的公文写作网站
  • 大连住房和建设局网站建站市场分析
  • 网站项目怎么做计划黄聪wordpress
  • 安徽道遂建设工程有限公司网站定制专业app开发
  • 网站做的好网站做不做百度云加速
  • 聚成网络网站建设做淘宝返利网站能挣钱
  • 网站优化怎么做深圳平面设计公司招聘
  • 原平的旅游网站怎么做的襄樊网站网站建设
  • 做家乡特产的网站网站模版怎么用
  • 建网站哪家最好微网站什么意思
  • 兔展在线制作网站仿爱范儿网wordpress主题
  • 抚宁区建设局网站福田建设网站
  • 黑龙江建设厅网站首页wordpress调用评论
  • 怎么样做网站 用网站赚钱提高wordpress+权重
  • 河北省建设执业注册中心网站河北外贸网站建设
  • mooc网站开发案例wordpress图片文件目录下
  • 网站备案是先做网站上线还是苏州专业高端网站建设企业
  • 家庭路由器建个人网站企业seo优化服务
  • 丽江北京网站建设店面设计师岗位职责
  • 网站设计psd模板清河做网站多少钱
  • 南京网页网站制作国外网站源代码
  • 网站建设工作总结搜索推广代运营
  • 全球优秀企业网站无尺码精品产品
  • 网站建设方案应该怎么写中关村在线
  • 龙岩做网站价格毕设网站和系统的区别
  • 在服务器上布网站怎么做的山东公路建设集团网站
  • 佛山南海区建网站的公司wordpress支付免签约插件