<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-61  評論-13  文章-19  trackbacks-0

    單例模式也屬于創建型模式,所謂單例,顧名思義,所指的就是單個實例,也就是說要保證一個類僅有一個實例。
                      單例模式有以下的特點:
                      ①
                      單例類只能有一個實例
                      ②
                      單例類必須自己創建自己的唯一實例
                      ③
                      單例類必須給所有其他對象提供這一實例
                      下面我們就來寫一個簡單的單例模式的例子:
                      Public class Singleton1{
                      Private static final Singleton1 instance=new Singleton1();
                      //私有的默認構造函數
                      Private Singleton1(){}
                      //靜態工廠方法
                      Public static Singleton1 getInstance(){
                      Return instance;
                      }
                      }
                      大家可以看出來,在這個類被加載時,靜態變量instance會被初始化,此時該類的私有構造函數被調用,這時候,單例類的唯一實例就被創建出來了
                      值得注意的是:由于構造函數是私有的,因此該類不能被繼承
                      還有一種寫法也可以實現單例模式:
                      Public class Singleton2{
                      Private static final Singleton2 instance=null;
                      //私有的默認構造函數
                      Public Singleton1(){}
                      //靜態工廠方法
                      Public synchronized static Singleton2 getInstance(){
                      If(instance==null){
                      Instance=new Singleton2();
                      }
                      Return instance;
                      }
                      }
                      這種寫法和第一種的區別在于:實例并沒有直接實例化,而是在靜態工廠方法被調用的時候才進行的,而且對靜態工廠方法使用了同步化,以處理多線程并發的環境。
                      這兩種寫法還有兩個非常有意思的名字:第一種稱為餓漢式單例,第二種稱為懶漢式單例。至于為什么起這個名字,自己好好想想吧。
                      餓漢式單例在自己被加載時就將自己實例化,如果從資源利用效率角度來講,比懶漢式單例類稍差些。但是從速度和反應時間角度來講,則比懶漢式要稍好些。
                      但是遺憾的是:懶漢式單例類也不能被繼承。
                      我們克服前兩種單例類不能被繼承的缺點,我們可以使用另外一種特殊化的單例模式,它被稱為單例注冊表。
                      Import java.util.HashMap;
                      Public class RegSingleton{
                      Static private HashMap registry=new HashMap();
                      //靜態塊,在類被加載時自動執行
                      Static{
                      RegSingleton rs=new RegSingleton();
                      Registry.put(rs.getClass().getName(),rs);
                      }
                      //受保護的默認構造函數,如果為繼承關系,則可以調用,克服了單例類不能為繼承的缺點
                      Protected RegSingleton(){}
                      //靜態工廠方法,返回此類的唯一實例
                      public static RegSingleton getInstance(String name){
                      if(name==null){
                      name=” RegSingleton”;
                      }
                      if(registry.get(name)==null){
                      try{
                      registry.put(name,Class.forName(name).newInstance());
                      }
                      Catch(Exception ex){ex.printStackTrace();}
                      }
                      Return (RegSingleton)registry.get(name);
                      }
                      }
                      下面我們來看看Spring中的單例實現,當我們試圖從Spring容器中取得某個類的實例時,默認情況下,Spring會才用單例模式進行創建。
                      <bean id="date" class="java.util.Date"/>
                      <bean id="date" class="java.util.Date" scope="singleton"/>
                      (僅為Spring2.0支持)
                      <bean id="date" class="java.util.Date" singleton="true"/>
                      以上三種創建對象的方式是完全相同的,容器都會向客戶返回Date類的單例引用。那么如果我不想使用默認的單例模式,每次請求我都希望獲得一個新的對象怎么辦呢?很簡單,將scope屬性值設置為prototype(原型)就可以了
                      <bean id="date" class="java.util.Date" scope="prototype"/>
                      通過以上配置信息,Spring就會每次給客戶端返回一個新的對象實例。
                      那么Spring對單例的底層實現,到底是餓漢式單例還是懶漢式單例呢?呵呵,都不是。Spring框架對單例的支持是采用單例注冊表的方式進行實現的,源碼如下:
                      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;
                      }
                      }
                      以上的源碼對于很多同學來說,可能感覺比較恐怖,但是學習要學會抓住要領,剛才的源碼中,大家真正要記住的是Spring對bean實例的創建是采用單例注冊表的方式進行實現的,而這個注冊表的緩存是HashMap對象,如果配置文件中的配置信息不要求使用單例,Spring會采用新建實例的方式返回對象實例

    posted on 2010-01-21 09:52 xnabx 閱讀(1723) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产又黄又爽又刺激的免费网址| 一个人免费观看日本www视频 | 4虎1515hh永久免费| A毛片毛片看免费| 国产视频精品免费视频| 国产特黄一级一片免费| 一区二区三区在线免费观看视频| 免费国产黄网站在线看| 本道天堂成在人线av无码免费 | 亚洲国产理论片在线播放| 久久国产免费一区| 久久精品国产这里是免费| 91成人免费观看| 91香蕉成人免费网站| 成人免费毛片内射美女-百度| 国产精品成人免费视频网站京东 | 在线免费观看你懂的| aⅴ在线免费观看| 2022国内精品免费福利视频| 一区二区三区免费精品视频| 国产情侣久久久久aⅴ免费| 1000部啪啪未满十八勿入免费 | 国产成人自产拍免费视频| 最近的2019免费中文字幕| 一级做a爰全过程免费视频| 日日麻批免费40分钟日本的| 成人免费视频软件网站| 五月婷婷亚洲综合| 一个人看www在线高清免费看| 免费看大美女大黄大色| 亚洲国产成人久久综合碰| 国产V亚洲V天堂无码| 亚洲剧场午夜在线观看| 久久人午夜亚洲精品无码区| 亚洲视频一区二区三区四区| 4444亚洲国产成人精品| 亚洲gv猛男gv无码男同短文| 亚洲国产情侣一区二区三区| 免费亚洲视频在线观看| 国产精品免费福利久久| 免费被黄网站在观看|