国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Spring設(shè)計(jì)模式——單例模式

 


單例模式也屬于創(chuàng)建型模式,所謂單例,顧名思義,所指的就是單個(gè)實(shí)例,也就是說要保證一個(gè)類僅有一個(gè)實(shí)例。
單例模式有以下的特點(diǎn):

單例類只能有一個(gè)實(shí)例

單例類必須自己創(chuàng)建自己的唯一實(shí)例

單例類必須給所有其他對象提供這一實(shí)例

下面我們就來寫一個(gè)簡單的單例模式的例子:
Public class Singleton1{
Private static final Singleton1 instance=new Singleton1();
//私有的默認(rèn)構(gòu)造函數(shù)
Private Singleton1(){}
//靜態(tài)工廠方法
Public static Singleton1 getInstance(){

Return instance;
}
}
大家可以看出來,在這個(gè)類被加載時(shí),靜態(tài)變量instance會(huì)被初始化,此時(shí)該類的私有構(gòu)造函數(shù)被調(diào)用,這時(shí)候,單例類的唯一實(shí)例就被創(chuàng)建出來了

值得注意的是:由于構(gòu)造函數(shù)是私有的,因此該類不能被繼承

還有一種寫法也可以實(shí)現(xiàn)單例模式:
Public class Singleton2{
Private static final Singleton2 instance=null;
//私有的默認(rèn)構(gòu)造函數(shù)
Public Singleton1(){}
//靜態(tài)工廠方法
Public synchronized static Singleton2 getInstance(){

If(instance==null){

Instance=new Singleton2();
}

Return instance;
}
}

這種寫法和第一種的區(qū)別在于:實(shí)例并沒有直接實(shí)例化,而是在靜態(tài)工廠方法被調(diào)用的時(shí)候才進(jìn)行的,而且對靜態(tài)工廠方法使用了同步化,以處理多線程并發(fā)的環(huán)境。
這兩種寫法還有兩個(gè)非常有意思的名字:第一種稱為餓漢式單例,第二種稱為懶漢式單例。至于為什么起這個(gè)名字,自己好好想想吧。
餓漢式單例在自己被加載時(shí)就將自己實(shí)例化,如果從資源利用效率角度來講,比懶漢式單例類稍差些。但是從速度和反應(yīng)時(shí)間角度來講,則比懶漢式要稍好些。

但是遺憾的是:懶漢式單例類也不能被繼承。

我們克服前兩種單例類不能被繼承的缺點(diǎn),我們可以使用另外一種特殊化的單例模式,它被稱為單例注冊表。
Import java.util.HashMap;
Public class RegSingleton{
Static private HashMap registry=new HashMap();
//靜態(tài)塊,在類被加載時(shí)自動(dòng)執(zhí)行
Static{

RegSingleton rs=new RegSingleton();

Registry.put(rs.getClass().getName(),rs);
}
//受保護(hù)的默認(rèn)構(gòu)造函數(shù),如果為繼承關(guān)系,則可以調(diào)用,克服了單例類不能為繼承的缺點(diǎn)
Protected RegSingleton(){}
//靜態(tài)工廠方法,返回此類的唯一實(shí)例
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中的單例實(shí)現(xiàn),當(dāng)我們試圖從Spring容器中取得某個(gè)類的實(shí)例時(shí),默認(rèn)情況下,Spring會(huì)才用單例模式進(jìn)行創(chuàng)建。
<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"/>

以上三種創(chuàng)建對象的方式是完全相同的,容器都會(huì)向客戶返回Date類的單例引用。那么如果我不想使用默認(rèn)的單例模式,每次請求我都希望獲得一個(gè)新的對象怎么辦呢?很簡單,將scope屬性值設(shè)置為prototype(原型)就可以了

<bean id="date" class="java.util.Date" scope="prototype"/>

通過以上配置信息,Spring就會(huì)每次給客戶端返回一個(gè)新的對象實(shí)例。

那么Spring對單例的底層實(shí)現(xiàn),到底是餓漢式單例還是懶漢式單例呢?呵呵,都不是。Spring框架對單例的支持是采用單例注冊表的方式進(jìn)行實(shí)現(xiàn)的,源碼如下:

public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{

/**

* 充當(dāng)了Bean實(shí)例的緩存,實(shí)現(xiàn)方式和單例注冊表相同

*/

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名有非法字符(或則做轉(zhuǎn)碼)

String beanName=transformedBeanName(name);

Object bean=null;

 

//手工檢測單例注冊表

Object sharedInstance=null;

 

//使用了代碼鎖定同步塊,原理和同步方法相似,但是這種寫法效率更高

synchronized(this.singletonCache){

sharedInstance=this.singletonCache.get(beanName);

}

if(sharedInstance!=null){

...

//返回合適的緩存Bean實(shí)例

bean=getObjectForSharedInstance(name,sharedInstance);

}else{

...

//取得Bean的定義

RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);

...

//根據(jù)Bean定義判斷,此判斷依據(jù)通常來自于組件配置文件的單例屬性開關(guān)

//<bean id="date" class="java.util.Date" scope="singleton"/>

//如果是單例,做如下處理

if(mergedBeanDefinition.isSingleton()){

synchronized(this.singletonCache){

//再次檢測單例注冊表

sharedInstance=this.singletonCache.get(beanName);

if(sharedInstance==null){

...

try {

//真正創(chuàng)建Bean實(shí)例


sharedInstance=createBean(beanName,mergedBeanDefinition,args);

//向單例注冊表注冊Bean實(shí)例

addSingleton(beanName,sharedInstance);


}


catch (Exception ex) {

 

...


}


finally{

 

...


}

}

}

bean=getObjectForSharedInstance(name,sharedInstance);

}

//如果是非單例,即prototpye,每次都要新創(chuàng)建一個(gè)Bean實(shí)例

//<bean id="date" class="java.util.Date" scope="prototype"/>

else{

bean=createBean(beanName,mergedBeanDefinition,args);

}

}

...

return bean;

}
}

以上的源碼對于很多同學(xué)來說,可能感覺比較恐怖,但是學(xué)習(xí)要學(xué)會(huì)抓住要領(lǐng),剛才的源碼中,大家真正要記住的是Spring對bean實(shí)例的創(chuàng)建是采用單例注冊表的方式進(jìn)行實(shí)現(xiàn)的,而這個(gè)注冊表的緩存是HashMap對象,如果配置文件中的配置信息不要求使用單例,Spring會(huì)采用新建實(shí)例的方式返回對象實(shí)例

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Spring 是怎么解決循環(huán)依賴的?
DefaultSingletonBeanRegistry
iOS單例實(shí)現(xiàn)2
iOS之單例模式初探
常用開源框架中設(shè)計(jì)模式使用分析 | 并發(fā)編程網(wǎng) – ifeve.com
關(guān)于 Spring 中 getBean 的全流程源碼解析
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服