什么是循环依赖问题
多个bean之间相互依赖,形成了一个闭环。比如:A依赖于B、B依赖于c、c依赖于A
通常来说,如果问spring容器内部如何解决循环依赖,一定是指默认的单例Bean中,属性互相引用的场景
两种注入方式对循环依赖的影响
官网:
循环依赖现象出现在Spring容器中注入依赖的对象,有两种情况:
- 构造器方式注入依赖,会报错
- 以set方式注入依赖,不会报错
我们AB循环依赖问题只要A的注入方式是setter且singleton ,就不会有循环依赖问题
Spring容器中:
- 默认的单例(singleton)的场景是支持循环依赖的,不报错
- 原型(Prototype)的场景是不支持循环依赖的,会报错
循环依赖报错:BeancurrentlyInCreationException
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘circulationa’: Requested bean is currently in creation: Is there an unresolvable circular reference?
Spring内部通过3级缓存解决循环依赖(DefaultsingletonBeanRegistry)
三级缓存是哪些map
第一级缓存(也叫单例池)singletonObjects:存放已经经历了完整生命周期的Bean对象
第二级缓存: earlySingletonObjects:存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整)
第三级缓存: Map
只有单例的bean会通过三级缓存提前暴露来解决循环依赖的问题,而非单例的bean,每次从容器中获取都是一个新的对象,都会重新创建,所以非单例的bean是没有缓存的,不会将其放到三级缓存中。
/** 一级缓存,spring初始化完成后,所有的单例bean都放在这里,是一个线程安全的map */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 二级缓存 存储AOP过程中产生的代理对象*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**三级缓存 value保存的是一个生产bean的工厂 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
A/B两个对象在三级缓存中的迁移
三级缓存循环依赖解决
如果没有二级是否可以?
如果没有循环依赖和AOP的场景下,二级缓存是不需要的;