乐趣区

关于2022招聘季:高频面试题说清楚Spring如何解决循环依赖

Spring 的循环依赖问题始终是中高级 Java 高频面试题之一,其中的考点就在于你对 Spring 中 bean 的加载过程是否有肯定的了解。

那么咱们就以下几点说一下。

Spring 中罕用的注入形式有哪几种?

结构器注入

set 办法注入

注解注入

对于这方面的常识之后再细聊,明天重点不是这些。

什么是循环依赖?

循环依赖,留神,这里说的是依赖,而不是调用,这是两个概念,肯定不要混同。

循环依赖从字面意思来看,就是 A 依赖 B,而后 B 依赖 A,当然,这个依赖过程也能够更长,不肯定就非要两个相互依赖,十个八个也是循环依赖,只有造成了一个闭环。

如图,这样就造成了一个闭环,简略说,如此依赖上来,就是一个死循环。

如何解决循环依赖?

Spring 中的循环依赖包含两种,结构器循环依赖和 setter 循环依赖。

结构器循环依赖

当应用结构器注入形式时,Spring 是无奈解决循环依赖的,在出问题时会报错,抛出 BeanCurrentlyInCreationException 异样。

模仿一下场景的话,大略如下:

  1. X1 在创立时,发现结构器须要 X2 类对象,只能去创立 X2;
  2. X2 在创立时,又发现结构器须要 X3 类对象,只能去创立 X3;
  3. X3 在创立时,又再次发现结构器须要 X1 对象;周而复始,最终抛出异样。

setter 循环依赖

次要来说一下 setter 循环依赖,通过 Spring 在创立 bean 时的一级、二级、三级缓存的概念解决的。

留神:这里解决的只是单例模式下的 setter 循环依赖,非单例模式下的仍然没有方法解决,在业务环境中该当尽量避免此类情况。

创立 Bean 的缓存概念:

一级缓存:singletonObjects,能够称为成品池,寄存齐全实例化属性赋值实现的 Bean,间接能够应用。

二级缓存:earlySingletonObjects,能够称为半成品池,寄存晚期 Bean 的援用,尚未属性拆卸的 Bean

三级缓存:singletonFactories,能够称为工厂池,寄存实例化实现的 Bean 工厂。

通过 setter 注入时,会经验以下几个过程。

看图谈话!

1)X1 在创立时,首先依据构造函数创立 bean,裸露一个 Factory 给三级缓存(工厂池),并且将其放入二级缓存(半成品池);而后进行属性的拆卸,发现有依赖关系,查问三级缓存是否存在,如没有,返回创立。

2)创立 X2 时,同 X1,返回创立 X3。

3)创立 X3 时,这时三级缓存中曾经存在 X1,即可间接注入,而后将 X3 的 bean 对象放入一级缓存(成品池)。

4)随后 X2、X1 顺次能够创立实现,并且放入一级缓存中。

5)如此就实现 setter 循环依赖问题的解决,外围就是这个三级缓存。

留神:这里的 bean 对象创立实现,放入一级缓存中时,会将对应的二级、三级缓存清掉。

本文参加了 SegmentFault 思否征文「如何“反杀”面试官?」,欢送正在浏览的你也退出。

退出移动版