Spring的循环依赖问题

spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类:

在Spring中将循环依赖的处理分成了3种情况:

  1. 构造器循环依赖
  2. setter循环依赖
  3. prototype范围的依赖处理

构造器循环依赖

通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。

如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建TestC,最终在创建TestC时发现又需要TestA,从而形成一个环,没办法创建。

Spring容器将每一个正在创建的bean标识符放在一个"当前创建bean池"中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在"当前创建bean池"里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从"当前创建bean池"中清除掉。

setter循环依赖

通过setter注入方式构成的循环依赖。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean。

  1. Spring容器创建单例"testA"bean,首先根据无参构造器创建bean,并暴露一个"ObjectFactory"用于返回一个提前暴露一个创建中的bean,并将"testA"标识符放到"当前创建bean池",然后进行setter注入"testB"。
  2. Spring容器创建单例"testB"bean,首先根据无参构造器创建bean,并暴露一个"ObjectFactory"用于返回一个提前暴露一个创建中的bean,并将"testB"标识符放到"当前创建bean池",然后进行setter注入"testC"。
  3. Spring容器创建单例"testC"bean,首先根据无参构造器创建bean,并暴露一个"ObjectFactory"用于返回一个提前暴露一个创建中的bean,并将"testC"标识符放到"当前创建bean池",然后进行setter注入"testA"。进行注入"testA"时由于提前暴露了"ObjectFactory"工厂,从而使用它返回提前暴露一个创建中的bean。
  4. 最后再依赖注入"testB"和"testA",完成setter注入。

prototype范围的依赖处理

对于"prototype"作用域bean,Spring容器无法完成依赖注入,因为Spring容器不进行缓存"prototype"作用域的bean,因此无法提前暴露一个创建中的bean。

对于"singleton"作用域bean,可以通过"setAllowCircularReferences(false);"来禁用循环引用。

时间: 2024-10-12 14:39:03

Spring的循环依赖问题的相关文章

Spring之循环依赖

转:http://my.oschina.net/tryUcatchUfinallyU/blog/287936 概述 如何检测循环依赖 循环依赖如何解决 Spring如何解决循环依赖 主要的几个缓存 主要步骤 Spring不能完全解决的循环依赖问题 面对Spring不能完全解决的现状,我们该如何处理 概述 入职的时候学习spring研究过循环依赖,现在再回顾下,发现啥都忘记了,还是得总结下来,故总结该文. 本文主要解决如下问题: 1.何为循环依赖 2.如何检测循环依赖 3.循环依赖可以如何解决 4

spring解决循环依赖

之前面试有被问到过,面试官很调皮,我擅长的点没有问,然后抽了一个点让我回答,这个点考察了源码的理解,当时只是大概记得是提前暴露,但是细节答得有些粗糙,特补充一下,,, protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == nul

spring学习——Ioc基础四(Di之循环依赖)

一. 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不是循环调用,循环调用是方法之间的环调用.如图3-5所示: 图3-5 循环引用 循环调用是无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误. Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循

spring循环依赖问题分析——待后续补充

新搞了一个单点登录的项目,用的cas,要把源码的cas-webapp改造成适合我们业务场景的项目,于是新加了一些spring的配置文件. 但是在项目启动时报错了,错误日志如下: 一月 08, 2016 11:01:34 下午 org.apache.catalina.core.StandardContext filterStart 严重: Exception starting filter springSecurityFilterChain org.springframework.beans.fa

Spring中-IOC-Bean的初始化-循环依赖的解决

前言 在实际工作中,经常由于设计不佳或者各种因素,导致类之间相互依赖.这些类可能单独使用时不会出问题,但是在使用Spring进行管理的时候可能就会抛出BeanCurrentlyInCreationException等异常 .当抛出这种异常时表示Spring解决不了该循环依赖,本文将简要说明Spring对于循环依赖的解决方法. 循环依赖的产生和解决的前提 循环依赖的产生可能有很多种情况,例如: A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象 A的构造方法中依赖了B的实例对象

Spring循环依赖

Spring-bean的循环依赖以及解决方式 Spring里面Bean的生命周期和循环依赖问题 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的相互依赖关系.循环调用其实就是一个死循环,除非有终结条件. Spring中循环依赖场景有: (1)构造器的循环依赖 (2)field属性的循环依赖 其中,构造器的循环依赖问题无法解决,只能拋出BeanCurre

测试一下25道Spring经典面试题你会几道?循环依赖面试详解

前言 先看看什么是循环依赖当一个ClassA依赖于ClassB,然后ClassB又反过来依赖ClassA,这就形成了一个循环依赖:ClassA -> ClassB -> ClassA循环依赖-->2个或以上bean 互相持有对方,最终形成闭环.Spring中循环依赖的场景:1.构造器的循环依赖.(spring也无能为力)2.setter循环依赖:field属性的循环依赖[setter方式 单例,默认方式-->通过递归方法找出当前Bean所依赖的Bean,然后提前缓存[会放入Cach

Spring循环依赖原因及如何解决

浅谈Spring解决循环依赖的三种方式 SpringBoot构造器注入循环依赖及解决 原文:https://www.baeldung.com/circular-dependencies-in-spring 代码:https://github.com/eugenp/tutorials/tree/master/spring-di 原文地址:https://www.cnblogs.com/liran123/p/11655604.html

spring怎么解决循环依赖

spring怎么解决循环依赖?首先会根据 beanName 从单例 bean 缓存中获取,如果不为空则直接返回 主要是从三个缓存中获取 (称他们为3级缓存),分别是: singletonObjects (1 单例对象的cache) earlySingletonObjects(2 提前暴光的单例对象的Cache ) singletonFactories (3 单例对象工厂的cache )getSingleton() 整个过程如下: 首先从一级缓存 singletonObjects 获取,如果没有且