Spring源码分析(十三)缓存中获取单例bean
Posted wuxiaofeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码分析(十三)缓存中获取单例bean相关的知识,希望对你有一定的参考价值。
摘要:本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。
介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了。前面已经提到过,单 例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再尝试从singletonFactories中加载。 因为在创建单例bean的时候会存在依赖注人的情况,而在创建依赖的时候为了避免循环依赖, Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加人到 缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。
@Override @Nullable public Object getSingleton(String beanName) { // 参数true设置标识允许早期依赖 return getSingleton(beanName, true); } /** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 检査缓存中是否存在实例 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 如果为空,则锁定全局变量并进行处理 synchronized (this.singletonObjects) { // 如果此bean正在加载则不处理 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策路存储在 singletonFactories ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 调用预先设定的getObject方法 singletonObject = singletonFactory.getObject(); // 记录在缓存中,earlySingletonObjects和singletonFactories互斥 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
这个方法因为涉及循环依赖的检测,以及涉及很多变量的记录存取,所以让很多读者摸不着头脑。这个方法首先尝试从singletonObjects面获取实例,如果获取不到再从earlySingletonObjects里面获取,如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject 来创建bean,并放到 earlySingletonObjects里面去,并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才会使用。
这甩涉及用于存储bean的不同的map,可能让读者感到崩溃,简单解释如下。
singletonObjects | 用于保存 beanName 和创建 bean 实例之间的关系,bean name -> bean instance |
singletonFactories | 用于保存beanName 和创建bean的工厂之间的关系,bean name -> ObjectFactory |
earlySingletonObjects | 也是保存beanName 和创建bean实例之间的关系,与 singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检測循环引用 |
registeredSingletons | 用来保存当前所有已注册的bean |
以上是关于Spring源码分析(十三)缓存中获取单例bean的主要内容,如果未能解决你的问题,请参考以下文章
Spring IOC 容器源码分析 - 创建单例 bean 的过程