Spring源碼解析之分析各 scope的bean創建(4)

在 Spring 中存在着不同的 scope,默認是 singleton,還有prototype等。下面便分析各個scope。

1.singleton。

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //獲取singletonObjects全局鎖
        synchronized (this.singletonObjects) {
            //獲取singletonObjects對應的bean實例
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //創建bean之前的處理,添加singletonsCurrentlyInCreation緩存
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //初始化bean 其實就是調用createBean()
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //後置處理,singletonsCurrentlyInCreation除去緩存
                    afterSingletonCreation(beanName);
                }
                //添加進入對應的緩存中,刷新對應緩存
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

 在isSingleton爲true情況下,getSingleton()和createBean()方法。

分析getSingleton,這個方法並不是核心區創建bean的函數,而是對創建前後進行邏輯操作和校驗。

  •  獲取singletonObjects全局鎖,並獲取對應的bean實例,如果bean存在直接返回。這樣可以確保單例模式只存在唯一的  bean實例
  • 如果不存在,進行beforeSingletonCreation(beanName),singletonsCurrentlyInCreation加入緩存
  • singletonFactory.getObject()調用createBean()創建bean
  • afterSingletonCreation去除singletonsCurrentlyInCreation緩存
  • addSingleton()添加刷新對應的緩存。
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

一個 put、一個 add、兩個 remove。singletonObjects 單例 bean 的緩存,singletonFactories 單例 beanFactory 的緩存,earlySingletonObjects “早期”創建的單例 bean 的緩存,registeredSingletons 已經註冊的單例緩存。

 

原型模式:

Object prototypeInstance = null;
try {
	beforePrototypeCreation(beanName);
	prototypeInstance = createBean(beanName, mbd, args);
}
finally {
	afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

原型模式的創建也是一樣的:

  • 調用 beforeSingletonCreation() 記錄加載原型模式 bean 之前的加載狀態,即前置處理。
  • 調用 createBean() 創建一個 bean 實例對象。
  • 調用 afterSingletonCreation() 進行加載原型模式 bean 後的後置處理。
  • 調用 getObjectForBeanInstance() 從 bean 實例中獲取對象。

其他:

String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
    Object scopedInstance = scope.get(beanName, () -> {
        beforePrototypeCreation(beanName);
        try {
            return createBean(beanName, mbd, args);
        }
        finally {
            afterPrototypeCreation(beanName);
        }
    });
    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
    throw new BeanCreationException(beanName,
            "Scope '" + scopeName + "' is not active for the current thread; consider " +
            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
            ex);
}

 

三個模塊最主要的兩個方法createBean()和getObjectForBeanInstance()。createBean()下篇會講解。getObjectForBeanInstance()是這樣解釋的(《Spring 源碼深度解析》):

這個方法主要是驗證以下我們得到的 bean 的正確性,其實就是檢測當前 bean 是否是 FactoryBean 類型的 bean,如果是,那麼需要調用該 bean 對應的 FactoryBean 實例的 getObject() 作爲返回值。無論是從緩存中獲得到的 bean 還是通過不同的 scope 策略加載的 bean 都只是最原始的 bean 狀態,並不一定就是我們最終想要的 bean。舉個例子,加入我們需要對工廠 bean 進行處理,那麼這裏得到的其實是工廠 bean 的初始狀態,但是我們真正需要的是工廠 bean 中定義 factory-method 方法中返回的 bean,而 getObjectForBeanInstance() 就是完成這個工作的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章