Spring中常用的設計模式:單例模式
阿新 • • 發佈:2018-11-16
在Spring中,Bean可以被定義為兩種模式:prototype(原型)和singleton(單例)。
- singleton(單例)
只有一個共享的例項存在,所有對這個Bean的請求都會返回這個唯一的例項。 - prototype(原型)
對這個Bean的每次請求都會建立一個新的bean例項,類似於new。
Spring依賴注入Bean例項預設是單例的。
Spring的依賴注入(包括lazy-init方式)都是發生在 AbstractBeanFactory 的 getBean 裡。
getBean 的 doGetBean 方法呼叫 getSingleton 進行Bean的建立。lazy-init方式(lazy-init=“false”),在使用者向容器第一次索要Bean時進行呼叫;非lazy-init方式(lazy-init=“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);
}
spring依賴注入時,使用了雙重判斷加鎖的單例模式。
首先從快取singletonObjects(實際上是一個map)中獲取Bean例項,如果為null,對快取singletonObjects加鎖,然後再從快取中獲取Bean,如果繼續為null,就建立一個Bean。
這樣雙重判斷,能夠避免在加鎖的瞬間,有其他依賴注入引發bean例項的建立,從而造成重複建立的結果。