spring依賴注入的bean默認都是單例模式,他們是怎麼建立的?spring
在AbstractBeanFactory類中的getBean方法中調用了getSingleton()方法來建立bean:緩存
@Nullable 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; }
spring依賴注入時,使用了雙重判斷加鎖的單例模式,首先從緩存MAP中獲取bean實例,若是爲null,對緩存map加鎖,而後再從緩存中獲取bean,若是繼續爲null,就建立一個bean。安全
Spring並無使用私有構造方法來建立bean,而是經過singletonFactory.getObject()返回具體beanName對應的ObjectFactory來建立bean。其實是調用了AbstractAutowireCapableBeanFactory的doCreateBean方法,返回了BeanWrapper包裝並建立的bean實例。併發
看一下Netty實現的單例模式app
public final class ReadTimeoutException extends TimeoutException { private static final long serialVersionUID = 169287984113283421L; public static final ReadTimeoutException INSTANCE = new ReadTimeoutException(); private ReadTimeoutException() { } }
類的定義十分簡單,包含一個私有的構造函數和一個static final 實例 :這樣其餘的調用者若是想獲取一個這個類的對象的話,訪問不到私有的構造函數,而只能經過instance拿到對象。函數
使用static final的好處是:當類被調用的時候,static final會初始化,JNI會給這個類添加一個同步塊,保證併發安全。this
另外這種方式只有當類被調用的時候纔會初始化一個實例。對象