Spring-IOC-嘗試從緩存中加載單例

單例在Spring的同一個容器中只會被創建一次,后續再獲取bean,就直接從單例緩存中獲取了。

  1. 先嘗試從SingletonObjects緩存中加載實例;如果不成功則嘗試從earlySingletonObjects中加載已經在創建完成之前提前暴露的單例Bean;如果失敗了,則從singletonFactories中獲取beanName對應的ObjectFactory,然后在調用ObjectFactory#getObject()方法創建對應的Bean,并放到earlySingletonObjects中,并從SingletonFactories中remove掉這個ObjectFactory。而對于后續的所有操作都只是為了循環依賴檢測時候使用,也就是allowEarlyReference為true的情況下才使用。

  2. 為了解決循環依賴的問題,Spring中創建bean的原則是不等bean創建完成就會將創建bean的ObjectFactory提前曝光加入到緩存中, 一旦下一個Bean創建時需要依賴上一個bean則直接使用ObjectFactory。

1. 從緩存中獲取單例bean
beans.factory.support.DefaultSingletonBeanRegistry
    @Override
    public Object getSingleton(String beanName) {
        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
     */
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        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的不同的map

  • singletonObjects

用于保存BeanName和創建bean實例之間的關系,bean name --> bean instance

  • singletonFactories

用于保存BeanName和創建bean的工廠之間的關系,bean name --> ObjectFactory

  • earlySingletonObjects

保運BeanName和創建bean實例之間的關系,與singletonObjects的不同在于,當一個單例bean被放到這里面后,name當bean還在創建過程中,就可以通過getBean方法獲取到了,其目的是用來檢測循環引用。

  • registeredSingletons

用來保存當前所有已注冊的單例bean

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容