共计 1165 个字符,预计需要花费 3 分钟才能阅读完成。
Spring 的循环依赖问题始终是中高级 Java 高频面试题之一,其中的考点就在于你对 Spring 中 bean 的加载过程是否有肯定的了解。
那么咱们就以下几点说一下。
Spring 中罕用的注入形式有哪几种?
结构器注入
set 办法注入
注解注入
对于这方面的常识之后再细聊,明天重点不是这些。
什么是循环依赖?
循环依赖,留神,这里说的是依赖,而不是调用,这是两个概念,肯定不要混同。
循环依赖从字面意思来看,就是 A 依赖 B,而后 B 依赖 A,当然,这个依赖过程也能够更长,不肯定就非要两个相互依赖,十个八个也是循环依赖,只有造成了一个闭环。
如图,这样就造成了一个闭环,简略说,如此依赖上来,就是一个死循环。
如何解决循环依赖?
Spring 中的循环依赖包含两种,结构器循环依赖和 setter 循环依赖。
结构器循环依赖
当应用结构器注入形式时,Spring 是无奈解决循环依赖的,在出问题时会报错,抛出 BeanCurrentlyInCreationException 异样。
模仿一下场景的话,大略如下:
- X1 在创立时,发现结构器须要 X2 类对象,只能去创立 X2;
- X2 在创立时,又发现结构器须要 X3 类对象,只能去创立 X3;
- 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 思否征文「如何“反杀”面试官?」,欢送正在浏览的你也退出。