三级缓存结构:
- 代码清单2-17 DefaultSingletonBeanRegistry中的三级缓存Map定义代码
// 第一级缓存:完整的bean实例.单例对象的缓存:bean name -> bean instance
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 第三季缓存:创建earlySingletonObjects的工厂对象.单例对象工厂的缓存:bean name -> ObjectFactory
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 第二级缓存:已经创建但还没有完成属性注入的对象.提前暴露的单例对象的缓存:bean name -> bean instance
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
getSingleton()方法分析:
在bean的加载过程中,单例在Spring的同一容器内只会被创建一次,后续再获取bean直接从单例缓存中获取。
尝试加载实例的顺序:singletonObjects -> earlySingletonObjects -> singletonFactories
尝试加载实例的原则:将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory
首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingleton- Objects里面获取,如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingleton-Objects里面去,并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才会使用。
singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name --> bean instance。
singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name --> ObjectFactory。
earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用。
registeredSingletons:用来保存当前所有已注册的bean。
《Spring源码深度解析(第2版)》
Bean的实例化过程中和循环依赖有关的代码:
//1. 创建Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
// 针对循环依赖问题提前暴露单例工厂类
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
//2. 注入属性
populateBean(beanName, mbd, instanceWrapper);