对于单例对象来说,在Spring的整个容器的生命周期内,有且只存在一个对象,很容易想到这个对象应该存在Cache中,Spring大量运用了Cache的手段,在循环依赖问题的解决过程中甚至使用了“三级缓存”。
// singletonObjects指单例对象的cache
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
// earlySingletonObjects指提前曝光的单例对象的cache
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
// singletonFactories指单例对象工厂的cache
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
获取对象过程:分析getSingleton的整个过程,Spring首先从singletonObjects(一级缓存)中尝试获取,如果获取不到并且对象在创建中,则尝试从earlySingletonObjects(二级缓存)中获取,如果还是获取不到并且允许从singletonFactories通过getObject获取,则通过singletonFactory.getObject()(三级缓存)获取。如果获取到了则将singletonObject放入到earlySingletonObjects,也就是 将三级缓存提升到二级缓存中!
如果 A 依赖B B 也依赖 A
A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,长大成人,进去了一级缓存singletonObjects中。
为什么spring要使用三级缓存,明明用二级缓存就能解决问题
Spring框架中的三级缓存是为了解决特定情况下的Bean循环依赖问题而设计的,而不是为了替代或解决二级缓存的问题。
在Spring中,Bean的创建过程中有一个重要的步骤是解决循环依赖,即当两个Bean相互依赖时,Spring需要确保它们都能正确地初始化,并且可以相互引用。为了实现这个目标,Spring引入了三级缓存机制,分别是singletonObjects、earlySingletonObjects和singletonFactories。
- singletonObjects: 这是一级缓存,用于存储已经完成创建并初始化的Bean对象。在Bean的创建过程中,当Spring发现一个Bean依赖另一个尚未完成初始化的同类型Bean时,它会尝试从这一级缓存中获取已经创建的Bean。
- earlySingletonObjects: 这是二级缓存,用于存储尚未完成初始化的Bean对象。当一个Bean正在创建过程中,如果发现它依赖另一个同类型的Bean,但该Bean尚未完成初始化,Spring会将其放入这一级缓存中,以便后续获取。
- singletonFactories: 这是三级缓存,用于存储用于创建Bean的对象工厂。当一个Bean正在创建过程中,如果发现它依赖另一个同类型的Bean,但该Bean尚未完成初始化,Spring会将创建该Bean的对象工厂放入这一级缓存中,以便后续使用。
通过使用三级缓存,Spring能够在处理循环依赖时确保Bean的正确初始化顺序,并且能够处理复杂的依赖关系。二级缓存无法提供这种级别的控制和管理。
需要注意的是,使用二级缓存是一种常见的缓存技术,用于在应用程序中提供性能优化。但Spring的三级缓存是为了处理Bean的循环依赖情况而引入的一种特殊机制,并不是用来替代或解决常规的缓存需求的。