spring循环注入异常问题的解决方案

今天在做项目的时候突然遇到一个问题:启动服务器的时候spring没报错,可是当我访问某个页面的时候spring报Request bean is currently in creation: is there an unresolvable circular reference的错误,后来查了些资源终于找出来了原因,这里和大家分享一下;

首先产生这个错误的原因是因为spring循环注入了,什么是循环注入?举个列子我有一个类A,A有一个构造器里面的参数是类B,然后类B里面有个构造器参数是类C,类C里面有个构造器参数是类A,就是我们会发现其实引用循环了A 里面有B的引用,B里面有C的引用,C里面又有A的引用。

循环依赖又分为构造器循环依赖和set循环依赖:

首先讲一下构造器的循环依赖:

public class A
{
  public A(B b)
  {
  }
}
public class B
{
  public B(C c)
  {
  }
}
public class C
{
  public C(A a)
  {
  }
}

当我们用spring来加载A的时候spring的流程是这样的:

1:spring创建A首先去当前创建池中去查找当前A是否在创建,如果发明没有创建则准备其构造器需要的参数B,然后把创建A的标识放入当前创建池中。

2:spring创建B首先去当前创建池中去查找当前B是否在创建,如果发现没有创建则准备其构造器需要的参数C,然后把创建B的标识放入当前创建池中。

3:spring创建C首先去当前创建池中去查找当前C是否在创建,如果发现没有创建则准备其构造器需要的参数A,然后把创建C的标识放入当前创建池中。

4:spring创建C需要的A,这个时候会发现在当前创建池中已经有A的标识,A正在创建中则抛出BeanCurrentlyInCreationException。

构造器的循环注入是没有办法解决的,所以只能我们避免.

接下来看下set方式的循环注入:

set方式的循环注入分2种情况,第一种情况是可以解决的循环注入就是单列情况下。第二种情况就是无法解决的循环注入就是多列情况下,下面分析一下原因:

先看第一种情况,还是拿上面的ABC3个类来说明问题,只不过这次不是构造器里面的参数,而是换成他们的成员变量,然后通过set方式类注入,这里代码就不写了直接讲下:

单列下set方式的注入流程是这样的:

1:spring创建A,首先根据其无参构造器创建一个对象A,然后提前暴露出创建出来的这个A对象,然后再当前的创建池中放入创建A的标识,然后进行set方法注入B。

2:spring创建B,首先根据其无参构造器创建一个对象B,然后提前暴露出创建出来的这个B对象,然后在当前的创建池中放入创建B的标识,然后进行set方法的注入C。

3:spring创建C,首先根据其无参构造器创建一个对象C,然后提前暴露出创建处理的这个C对象,然后在当前的创建池中放入创建C的标识,然后进行set方法的注入A。

4:在第三步注入A的时候由于提前暴露出来了创建出来的A对象所以不会报BeanCurrentlyInCreationException的错误。

多列下set方式的循环注入不能解决的原因是在多列的情况下,当创建对象的时候spring不会提前暴露创建处理的对象A,这样的话则会和构造器循环注入出现一样的情况最终导致报错。

解决办法:

去掉最后一层的注入或者中间某一层的注入。通过spring getBean的方式去获取对象

讲完了。讲的不对的地方谢谢提出来。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Spring循环依赖的三种方式(推荐)

    引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下spring是如果解决循环依赖的. 第一种:构造器参数循环依赖 Spring容器会将每一个正在创建的Bean 标识符放在一个"当前创建Bean池"中,Bean标识符在创建过程中将一直保持 在这个池中,因此如果在创建Bean过程中发现自己已经在"当前创建Bean池"里时将抛出 BeanCurrentlyInCrea

  • Spring中DAO被循环调用的时候数据不实时更新的解决方法

    在描述问题之前先说明几个前提,假设在Spring的配置文件中使用下面的方式配置了数据库的事务: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> <

  • 浅谈Spring解决循环依赖的三种方式

    引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种:构造器参数循环依赖 表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyIn CreationException异常表示循环依赖. 如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建Test

  • Spring循环依赖正确性及Bean注入的顺序关系详解

    一.前言 我们知道 Spring 可以是懒加载的,就是当真正使用到 Bean 的时候才实例化 Bean.当然也不全是这样,例如配置 Bean 的 lazy-init 属性,可以控制 Spring 的加载时机.现在机器的性能.内存等都比较高,基本上也不使用懒加载,在容器启动时候来加载bean,启动时间稍微长一点儿,这样在实际获取 bean 供业务使用时,就可以减轻不少负担,这个后面再做分析. 我们使用到 Bean 的时候,最直接的方式就是从 Factroy 中获取,这个就是加载 Bean 实例的源

  • spring boot启动时mybatis报循环依赖的错误(推荐)

    自己在做项目时,想使用热部署减少部署时间,于是添加了springboot-devtools 在maven中添加了依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> 然后正常的启动项目时发现控制台一直在不停的输出错误,错误如图 不明所以,然后就准备去调

  • 详解在springmvc中解决FastJson循环引用的问题

    我们先来看一个例子: package com.elong.bms; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import com.alibaba.fastjson.JSON; public class Test { public static void main(String[] args) { Map<String, Student> maps = new HashMap<

  • 详解Spring循环依赖的解决方案

    spring针对Bean之间的循环依赖,有自己的处理方案.关键点就是三级缓存.当然这种方案不能解决所有的问题,他只能解决Bean单例模式下非构造函数的循环依赖. 我们就从A->B->C-A这个初始化顺序,也就是A的Bean中需要B的实例,B的Bean中需要C的实例,C的Bean中需要A的实例,当然这种需要不是构造函数那种依赖.前提条件有了,我们就可以开始了.毫无疑问,我们会先初始化A.初始化的方法是org.springframework.beans.factory.support.Abstra

  • 详解Spring-bean的循环依赖以及解决方式

    本文主要是分析Spring bean的循环依赖,以及Spring的解决方式. 通过这种解决方式,我们可以应用在我们实际开发项目中. 1. 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的相互依赖关系.循环调用其实就是一个死循环,除非有终结条件. Spring中循环依赖场景有: (1)构造器的循环依赖 (2)field属性的循环依赖. 循环依赖的产生和解

  • 深入理解Spring中的循环依赖

    循环依赖 定义: 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比方CircularityA引用CircularityB,CircularityB引用CircularityC,CircularityC引用CircularityA.形成一个环状引用关系. 在使用Spring时,如果主要采用基于构造器的依赖注入方式,则可能会遇到循环依赖的情况,简而言之就是Bean A的构造器依赖于Bean B,Bean B的构造器又依赖于Bean A.在这种情况下Spring会在编译时抛出Bean

  • 详解Spring Bean的循环依赖解决方案

    如果使用构造函数注入,则可能会创建一个无法解析的循环依赖场景. 什么是循环依赖 循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的相互依赖关系.循环调用其实就是一个死循环,除非有终结条件. Spring中循环依赖场景有: (1)构造器的循环依赖 (2)field属性的循环依赖. 怎么检测是否存在循环依赖 检测循环依赖相对比较容易,Bean在创建的时候可以给该Bean打标,

随机推荐