Spring中循环依赖场景有:构造器的循环依赖;属性的循环依赖
singletonObjects:第一级缓存,里面放置的是实例化好的单例对象; earlySingletonObjects:第二级缓存,里面存放的是提前曝光的单例对象; singletonFactories:第三级缓存,里面存放的是要被实例化的对象的对象工厂
创建bean的时候Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取,如果还是获取不到就从三级缓存singletonFactories中取(Bean调用构造函数进行实例化后,即使属性还未填充,就可以通过三级缓存向外提前暴露依赖的引用值(提前曝光),根据对象引用能定位到堆中的对象,其原理是基于Java的引用传递),取到后从三级缓存移动到了二级缓存完全初始化之后将自己放入到一级缓存中供其他使用,
因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。
构造器循环依赖解决办法:在构造函数中使用@Lazy注解延迟加载。在注入依赖时,先注入代理对象,当首次使用时再创建对象说明:一种互斥的关系而非层次递进的关系,故称为三个Map而非三级缓存的缘由 完成注入;