【原创】Spring:从三级缓存结构中获取单例Bean

原创
2023/02/06 19:42
阅读数 135

三级缓存结构:

  • 代码清单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);

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部