1. 程式人生 > >Spring中常用的設計模式:單例模式

Spring中常用的設計模式:單例模式

在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例項的建立,從而造成重複建立的結果。