Spring是如何解决循环依赖(通俗易懂)
什么是循环依赖
循环依赖就是两个或多个bean相互之间持有对方
Spring如何解决循环依赖
-
构造器循环依赖
构造器循环依赖表示通过构造器注入构成的循环依赖,此循环依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。但这种注入方式其实已经很少使用了(但要知道) -
setter循环依赖
setter循环依赖表示通过setter注入方式构成的循环依赖。这种方式应该是Spring中用的最多的。
**Spring如何解决:**通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean。
**Spring具体做法:**使用Spring内部的三级缓存来解决
singletonObjects 一级缓存:用于保存实例化–>注入–>初始化完成的最终bean实例
earlySingletonObjects 二级缓存:用于保存实例化完成的bean实例,但bean中可能存在未赋值的属性
singletonFactories 三级缓存:用于保存bean创建工厂,以便于后面扩展有机会创建代理对象核心:Spring中bean的创建是分为两步的,先实例化后初始化。实例化是通过反射实现,初始化也就是对bean中的属性进行赋值,这一步是在实例化之后做的,那些实例化但没有初始化的bean就放在缓存中。Spring就是通过分先实例化后初始化两步走的,利用缓存来解决循环依赖的。
举例说明:
A --> B B --> A 对象A持有对象B,对象B持有对象A;
- prototype范围的依赖
对于prototype作用域的bean,Spring容器无法完成依赖注入,因为Spring容器不进行缓存scope为prototype作用域的bean,只有非抽象、单例并且非懒加载的类才能被提前加载,因此无法提前暴露一个scope为prototype的bean。