ioc循环依赖怎么解决

简介: ioc循环依赖怎么解决

循环依赖

循环依赖是指在Spring容器中,两个或多个bean互相持有对方,最终形成闭环。Spring容器无法创建这样的循环依赖,因为它会破坏依赖关系链。

在使用IoC(Inversion of Control)容器时,循环依赖是一个常见的问题。不同的IoC容器提供了不同的解决方案。在Spring框架中,常用的解决循环依赖的注解是 @Lazy@Autowired

1.@Lazy 注解:

在Spring中,@Lazy 注解可以用于延迟加载一个bean,从而解决循环依赖的问题。通过将 @Lazy 注解添加到类上,Spring 容器将会在第一次使用该bean时才去实例化它。

@Service
@Lazy
public class ClassA {
    @Autowired
    private ClassB classB;
}
@Service
@Lazy
public class ClassB {
    @Autowired
    private ClassA classA;
}

这样配置后,Spring 容器会在需要使用 ClassAClassB 时才进行实例化,从而避免了循环依赖问题

2.构造函数注入:

另一种常见的解决方式是通过构造函数注入,尽量避免使用字段注入。Spring 通过构造函数注入时,能够更好地处理循环依赖。

@Service
public class ClassA {
    private final ClassB classB;
    @Autowired
    public ClassA(ClassB classB) {
        this.classB = classB;
    }
}
@Service
public class ClassB {
    private final ClassA classA;
    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }
}

在实际应用中,综合使用 @Lazy 和构造函数注入可以有效地解决循环依赖问题。需要注意的是,循环依赖可能是代码结构问题的表现,因此在设计类之间的依赖关系时,也应该考虑是否可以进行重构以减少相互依赖。

其他方式

Spring的三级缓存

Spring的三级缓存主要用于解决单例的循环依赖问题。

当一个bean正在创建时,Spring会将其放入一个“当前创建Bean池”中。如果发现该bean已经在池中,就会抛出BeanCurrentlyInCreationException异常。通过这种方式,Spring容器可以检测到循环依赖的问题,并在创建bean时避免出现循环依赖。

具体来说,Spring的三级缓存包括以下三个级别:

  1. 第一级缓存:这个缓存是单例Bean的缓存,它会在应用程序启动时被加载,并存储在同一个单例Bean的实例中。当需要获取单例Bean时,Spring会首先检查第一级缓存,如果该Bean已经存在,就直接返回该Bean的实例。
  2. 第二级缓存:这个缓存是prototype Bean的缓存。与第一级缓存不同的是,第二级缓存中的Bean是prototype类型的,即每次获取Bean时都会创建一个新的实例。当需要获取prototype Bean时,Spring会首先检查第二级缓存,如果该Bean已经存在,就直接返回该Bean的实例。
  3. 第三级缓存:这个缓存是用于解决循环依赖问题的。当一个Bean正在创建时,Spring会将其放入一个“当前创建Bean池”中。如果发现该Bean已经在池中,就会抛出BeanCurrentlyInCreationException异常。这个异常表示该Bean正在创建中,不能再次创建。通过这种方式,Spring可以检测到循环依赖的问题,并在创建bean时避免出现循环依赖。

总之,Spring的三级缓存主要用于解决单例的循环依赖问题。在应用程序启动时,Spring会加载第一级缓存和第二级缓存,并在需要获取Bean时使用它们。如果遇到循环依赖的问题,Spring会使用第三级缓存来检测并避免问题的发生。

相关文章
|
6月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
缓存 Java Spring
【Spring使用三级缓存解决循环依赖的过程】
【Spring使用三级缓存解决循环依赖的过程】
|
缓存 Java Spring
Spring框架(四) 三级缓存与循环依赖
首先我们需要明白什么是循环依赖 , 打个比方 , 就是说A对象在创建的过程中 , 需要依赖注入B对象 , 但是B对象没有 , 就需要去创建 , 而在创建B对象的过程中又需要注入A对象 , A对象此时还在创建中,所以就构成了一个死循环 , A,B相互依赖 这样的关系被成为循环依赖(当然 , 可能还会有其他的情况),下面我们就来看看Spring是如何让解决循环依赖的
158 0
|
2月前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
188 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
1月前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
29 1
|
4月前
|
Java Spring
Spring循环依赖问题之构造器内的循环依赖如何解决
Spring循环依赖问题之构造器内的循环依赖如何解决
|
4月前
|
传感器
循环依赖问题之Bean循环依赖的定义是什么
循环依赖问题之Bean循环依赖的定义是什么
循环依赖问题之Bean循环依赖的定义是什么
|
4月前
|
存储 缓存 Java
Spring循环依赖问题之循环依赖异常如何解决
Spring循环依赖问题之循环依赖异常如何解决
|
6月前
|
缓存 Java 网络架构
从简入繁介绍springbean的循环依赖
【4月更文挑战第11天】Spring Bean的循环依赖是Spring框架中一个比较复杂且有趣的话题,涉及到Spring的核心容器、Bean生命周期和依赖注入机制。我将从简入繁地介绍这一概念,确保即使是初学者也能理解。
56 1
|
6月前
|
Java 测试技术 Spring
什么是循环依赖,如何解决?
在 Spring 应用中,循环依赖指的是两个或多个 Bean 之间相互引用,造成了一个环状的依赖关系。举例来说,如果 Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A,就形成了循环依赖。这种情况下,Spring 容器在创建这些 Bean 时会陷入无限循环,导致应用启动失败或者出现其他不可预测的问题。
108 1