一. 循环依赖:A对象中需要B;B对象中又需要A

二.三级缓存

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);//一级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);//二级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);//三级缓存

三.解决循环依赖的理论依据

Java基于引用传递,当我们获取到对象的引用时,对象的field或者或属性可以延后设置
Spring单例对象的初始化其实可以分为三步:(实例化、填充属性、初始化)

createBeanInstance:实例化,此时只是调用了构造方法,默认空构造器
populate:填充属性
initializeBean:初始化

四.具体步骤

五.几个问题

    1.构造器循环依赖的话,可以解决吗?

      不行,提前暴露的对象默认是无参构造器new出来的对象,构造器产生循环依赖,无解

      A构造方法依赖B,B构造方法依赖A;无解

      A构造方法依赖B;B set方法不依赖A; 先创建B有解,先创建A无解

      A set方法依赖B,B构造方法依赖A; 先创建A有解,先创建B无解

      A set方法依赖B,B set方法依赖A;有解

    2.为什么要三级,二级不行吗?三级缓存中为什么存了ObjectFactory?

       正常情况下,二级缓存其实就可以实现解决循环依赖的问题

  三级缓存主要是是为了更好的扩展,三级缓存存的是ObjectFactory的接口实现类,在getObject()方法中,调用了getEarlyBeanReference方法,主要是增加                                              SmartInstantiationAwareBeanPostProcessor后置处理的逻辑,包装原始类,如利用动态代理增强原始类等

    3.为什么要锁定,锁定的目的是什么?

      锁定的目的肯定是为了占有,这里是独占,防止多线程操作;如果不锁定,在不同线程中调用容器getBean的方法,可能会出现同时操作一级缓存的情况,而且这里,一级缓存用        了ConcurrentHashMap,二级、三级只是HashMap

    4.非单例可以吗?

     不行,Spring对于循环依赖的解决不是无条件的,首先前提条件是针对scope单例并且没有显式指明不需要解决循环依赖的对象,而且要求该对象没有被代理过