spring中的循环依赖是什么?

124 阅读3分钟

前言

之前面试的时候,面试官上我谈谈spring,说道spring那必然首先想到的就是这个ioc和aop了,巴拉巴拉说完之后,面试官满意的点点头,紧接着就又问那你有知道什么是spring的循环依赖吗,怎样解决循环依赖呢?今天我们就来简单的了解一下。

什么是spring的循环依赖?

就是两个或则两个以上的bean对象互相依赖对方,最终形成闭环。 举个例子:有一个A对象依赖了B对象,而B对象也依赖了A对象。这就是循环依赖。

在 Spring 中,一个对象并不是我们想象中直接new 出来的,它是会经过一系列 Bean 的生命周期经进行创建的,也正是因为 Bean 的生命周期所以才会出现循环依赖问题。spring在创建bean的时候,过程如下六个阶段:

实例化前》》实例化bean(推断构造)》》实例化后》》填充属性》》初始化前》》初始后;

而出现循环依赖问题一般是发生在第四步进行属性填充的时候。

比如一个对象A,A 对象中存在一个 B 对象的 b 属性,所以,当 A 对象生成了一个原始对象bean后,就会去给 对象B的b 属性去赋值,此时就会根据 b 属性的类型和属性名去 BeanFactory 工厂中去获取 B 对象所对应的单例bean。如果此时 BeanFactory 中存在 B 对应的 Bean,那么直接拿来赋值给 b 属性; 但如果此时 BeanFactory 中不存在 B 对应的 Bean,则需要生成一个 B 对应的 Bean,然后赋值给 b属性。

问题就出现在后面这种情况,找不到对应的bean,如果此时 B 类在 BeanFactory 中还没有生成相应的 Bean,这就需要去生成,就会经过 B 的 Bean 的生命周期。

而在创建 B 对象的 Bean 的过程中,恰好 B 类中存在一个 A 类的 a 属性,在创建 B 的 Bean 的过程中就需要 A 类对应的 Bean,但 B 类 Bean 的创建的条件是 A 类 Bean 在创建过程中的依赖注入而A有需要B的属性,这就形成了循环依赖,无法正常创建:

A Bean创建–>依赖了 B 属性–>触发 B Bean创建—>B 依赖了 A 属性—>需要 A Bean(但A Bean还在创建过程中)

从而导致 A Bean 创建不出来,B Bean 也创建不出来,这就是spring的循环依赖。

image.png

循环依赖的问题在Spring中主要有以下三种情况:

  • 通过构造方法进行依赖注入时产生的循环依赖问题。
  • 通过setter方法进行依赖注入且是在多例模式下产生的循环依赖问题。
  • 通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。

注意:在Spring中,只有最后一种的循环依赖问题被解决了,其他两种在遇到循环依赖问题后皆会产生异常。