什么是循环依赖问题

多个bean之间相互依赖,形成了一个闭环。比如:A依赖于B、B依赖于c、c依赖于A
通常来说,如果问spring容器内部如何解决循环依赖,一定是指默认的单例Bean中,属性互相引用的场景
image.png

两种注入方式对循环依赖的影响

官网:
image.png
循环依赖现象出现在Spring容器中注入依赖的对象,有两种情况:

  • 构造器方式注入依赖,会报错
  • 以set方式注入依赖,不会报错

我们AB循环依赖问题只要A的注入方式是settersingleton ,就不会有循环依赖问题

Spring容器中:

  • 默认的单例(singleton)的场景是支持循环依赖的,不报错
  • 原型(Prototype)的场景是不支持循环依赖的,会报错

  • 循环依赖报错:BeancurrentlyInCreationException

    image.png
    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> singletonFactories:存放可以生成Bean 的工厂
只有单例的bean会通过三级缓存提前暴露来解决循环依赖的问题,而非单例的bean,每次从容器中获取都是一个新的对象,都会重新创建,所以非单例的bean是没有缓存的,不会将其放到三级缓存中。

  1. /** 一级缓存,spring初始化完成后,所有的单例bean都放在这里,是一个线程安全的map */
  2. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  3. /** 二级缓存 存储AOP过程中产生的代理对象*/
  4. private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  5. /**三级缓存 value保存的是一个生产bean的工厂 */
  6. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

A/B两个对象在三级缓存中的迁移
image.png

三级缓存循环依赖解决

image.png
image.png
image.png

image.png

image.png

如果没有二级是否可以?

如果没有循环依赖和AOP的场景下,二级缓存是不需要的;