1. 程式人生 > >Spring中的設計模式-單例模式

Spring中的設計模式-單例模式

單例模式確保一個類在應用中只有一個例項

       我們以依賴注入建立bean例項為線索分析一下spring中單例模式。

       Spring的依賴注入(包括lazy-init方式)都是發生在AbstractBeanFactory的getBean裡。getBean的doGetBean方法呼叫getSingleton進行bean的建立。lazy-init方式,在容器初始化時候進行呼叫,非lazy-init方式,在使用者向容器第一次索要bean時進行呼叫。

帶同步的單例模式

下面是單例模式的核心程式碼。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null) {
   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依賴注入時,使用了雙重判斷加鎖的單例模式,首先從快取中獲取bean例項,如果為null,對快取map加鎖,然後再從快取中獲取bean,如果繼續為null,就建立一個bean。這樣雙重判斷,能夠避免在加鎖的瞬間,有其他依賴注入引發bean例項的建立,從而造成重複建立的結果。

      在這裡Spring並沒有使用私有構造方法來建立bean,而是通過singletonFactory.getObject()返回具體beanName對應的ObjectFactory來建立bean。我們一路跟蹤下去,發現實際上是呼叫了AbstractAutowireCapableBeanFactory的doCreateBean方法,返回了BeanWrapper包裝並建立的bean例項。

(ObjectFactory主要檢查是否有使用者定義的BeanPostProcessor後處理內容,並在建立bean時進行處理,如果沒有,就直接返回bean本身)

見如下程式碼:

8行建立bean例項返回給BeanWrapper

30行addSingletonFactory增加beanName和ObjectFactory的鍵值對應關係。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}....


getEarlyBeanReference獲取bean的所有後處理器,並進行處理。如果是SmartInstantiationAwareBeanPostProcessor型別,就進行處理,如果沒有相關處理內容,就返回預設的實現。

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
					if (exposedObject == null) {
						return exposedObject;
					}
				}
			}
		}
		return exposedObject;
	}


另外,在Spring的其他程式碼中也有使用的單例模式,如AOP的切點定義中。

公有靜態成員,私有建構函式的單例模式

class TruePointcut implements Pointcut, Serializable {
	
	private static final TruePointcut INSTANCE = new TruePointcut();
	
	/**
	 * Enforce Singleton pattern.
	 */
	private TruePointcut() {
	}

	....
       public static TruePointcut getInstance(){
        return INSTANCE;
      }
}

上面的程式碼可以改成:靜態工廠方法的單例模式

class TruePointcut implements Pointcut, Serializable {
    
    private static final TruePointcut INSTANCE = new TruePointcut();
    
    /**
     * Enforce Singleton pattern.
     */
    private TruePointcut() {
    }

    ....
       public static TruePointcut getInstance(){
        return INSTANCE;
      }
}

或者改成:用列舉實現單例模式

enum TruePointcut implements Pointcut, Serializable {
    
    INSTANCE ;
...    

}