Spring框架對單例的支持是採用單例註冊表的方式進行實現的,源碼以下:java
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{ /** * 充當了Bean實例的緩存,實現方式和單例註冊表相同 */ private final Map singletonCache=new HashMap(); public Object getBean(String name)throws BeansException{ return getBean(name,null,null); } ... public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{ //對傳入的Bean name稍作處理,防止傳入的Bean name名有非法字符(或則作轉碼) String beanName=transformedBeanName(name); Object bean=null; //手工檢測單例註冊表 Object sharedInstance=null; //使用了代碼鎖定同步塊,原理和同步方法類似,可是這種寫法效率更高 synchronized(this.singletonCache){ sharedInstance=this.singletonCache.get(beanName); } if(sharedInstance!=null){ ... //返回合適的緩存Bean實例 bean=getObjectForSharedInstance(name,sharedInstance); }else{ ... //取得Bean的定義 RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false); ... //根據Bean定義判斷,此判斷依據一般來自於組件配置文件的單例屬性開關 //<bean id="date" class="java.util.Date" scope="singleton"/> //若是是單例,作以下處理 if(mergedBeanDefinition.isSingleton()){ synchronized(this.singletonCache){ //再次檢測單例註冊表 sharedInstance=this.singletonCache.get(beanName); if(sharedInstance==null){ ... try { //真正建立Bean實例 sharedInstance=createBean(beanName,mergedBeanDefinition,args); //向單例註冊表註冊Bean實例 addSingleton(beanName,sharedInstance); }catch (Exception ex) { ... }finally{ ... } } } bean=getObjectForSharedInstance(name,sharedInstance); } //若是是非單例,即prototpye,每次都要新建立一個Bean實例 //<bean id="date" class="java.util.Date" scope="prototype"/> else{ bean=createBean(beanName,mergedBeanDefinition,args); } } ... return bean; } }