(一)Spring IoC源码-2.bean的加载-02从缓存中获取单例bean

版权声明:本文版权归作者所有,欢迎转载。转载时请在文章明显位置给出作者名字(潘威威)及原文链接。请勿将本文用于任何商业用途。 https://blog.csdn.net/panweiwei1994/article/details/79868480

本文已收录于【Spring源码札记专栏】

关联文章:
(一)Spring IoC源码-2.bean的加载-01整体概览
(一)Spring IoC源码-2.bean的加载-02从缓存中获取单例bean
(一)Spring IoC源码-2.bean的加载-03从bean实例中获取对象
(一)Spring IoC源码-2.bean的加载-04创建bean

从缓存中获取单例bean是通过DefaultSingletonBeanRegistry.getSingleton(String)实现的。

@Override
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //首先从singletonObjects中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    //如果没有获取到,且bean正在创建过程中(isSingletonCurrentlyInCreation()为true),则尝试从singletonFactories中获取
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

单例bean在同一个Spring容器中只创建一次,获取bean的时候,尝试从缓存加载bean。首先从singletonObjects中获取,如果没有获取到,且bean正在创建过程中(isSingletonCurrentlyInCreation()为true),则尝试从earlySingletonObjects中获取,如果还获取不到,就求助于singletonFactories。因为spring创建单例bean的时候,存在循环依赖的问题。比如创建bean a的时候发现bean a引用了bean b,此时会去创建bean b,但又发现bean b引用了bean c,所以此时会去创建bean c,在创建bean c的过程中发现bean c引用bean a。为了避免循环依赖,Spring采取了一种将正在创建的bean实例提早暴露加入到singletonFactories缓存中,一旦下一个bean创建的时候需要依赖上个bean,则直接使用singletonFactories来获取bean。

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** Set of registered singletons, containing the bean names in registration order */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

提前暴露bean实例到缓存的时机是在bean实例创建(调用构造方法)之后,初始化bean实例(属性注入)之前。具体在AbstractAutowireCapableBeanFactory类的protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {...}方法中。在该方法中调用了DefaultSingletonBeanRegistry类的addSingletonFactory方法提前暴露bean实例到缓存。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/panweiwei1994/article/details/79868480