Spring(四):Bean的作用域

摘自:http://jinnianshilongnian.iteye.com/blog/1415463

Bean的作用域

什么是作用域呢?即“scope”,在面向?qū)ο蟪绦蛟O(shè)計(jì)中一般指對(duì)象或變量之間的可見(jiàn)范圍。而在Spring容器中是指其創(chuàng)建的Bean對(duì)象相對(duì)于其他Bean對(duì)象的請(qǐng)求可見(jiàn)范圍。

Spring提供“singleton”和“prototype”兩種基本作用域,另外提供“request”、“session”、“global session”三種web作用域;Spring還允許用戶(hù)定制自己的作用域。

基本的作用域

singleton:

指“singleton”作用域的Bean只會(huì)在每個(gè)Spring IoC容器中存在一個(gè)實(shí)例,而且其完整生命周期完全由Spring容器管理。對(duì)于所有獲取該Bean的操作Spring容器將只返回同一個(gè)Bean。

GoF單例設(shè)計(jì)模式指“保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)訪(fǎng)問(wèn)它的全局訪(fǎng)問(wèn)點(diǎn)”,介紹了兩種實(shí)現(xiàn):通過(guò)在類(lèi)上定義靜態(tài)屬性保持該實(shí)例和通過(guò)注冊(cè)表方式。

1)通過(guò)在類(lèi)上定義靜態(tài)屬性保持該實(shí)例:

一般指一個(gè)Java虛擬機(jī) ClassLoader裝載的類(lèi)只有一個(gè)實(shí)例,一般通過(guò)類(lèi)靜態(tài)屬性保持該實(shí)例,這樣就造成需要單例的類(lèi)都需要按照單例設(shè)計(jì)模式進(jìn)行編碼;Spring沒(méi)采用這種方式,因?yàn)樵摲绞綄儆谇秩胧皆O(shè)計(jì)。

public class Singleton {  
    //1.私有化構(gòu)造器  
    private Singleton() {}  
    //2.單例緩存者,惰性初始化,第一次使用時(shí)初始化  
    private static class InstanceHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
    //3.提供全局訪(fǎng)問(wèn)點(diǎn)  
    public static Singleton getInstance() {  
        return InstanceHolder.INSTANCE;  
    }  
    //4.提供一個(gè)計(jì)數(shù)器來(lái)驗(yàn)證一個(gè)ClassLoader一個(gè)實(shí)例  
    private int counter=0;  
} 

2)通過(guò)注冊(cè)表方式:

首先將需要單例的實(shí)例通過(guò)唯一鍵注冊(cè)到注冊(cè)表,然后通過(guò)鍵來(lái)獲取單例,讓我們直接看實(shí)現(xiàn)吧,注意本注冊(cè)表實(shí)現(xiàn)了Spring接口“SingletonBeanRegistry”,該接口定義了操作共享的單例對(duì)象,Spring容器實(shí)現(xiàn)將實(shí)現(xiàn)此接口;所以共享單例對(duì)象通過(guò)“registerSingleton”方法注冊(cè),通過(guò)“getSingleton”方法獲取,消除了編程方式單例。

public class SingletonBeanRegister implements SingletonBeanRegistry {  
    //單例Bean緩存池,此處不考慮并發(fā)  
    private final Map<String, Object> BEANS = new HashMap<String, Object>();  
    public boolean containsSingleton(String beanName){  
        return BEANS.containsKey(beanName);  
    }  
    public Object getSingleton(String beanName) {  
        return BEANS.get(beanName);  
    }  
    @Override  
    public int getSingletonCount() {  
        return BEANS.size();  
    }  
    @Override  
    public String[] getSingletonNames() {  
        return BEANS.keySet().toArray(new String[0]);  
    }  
    @Override  
    public void registerSingleton(String beanName, Object bean) {  
        if(BEANS.containsKey(beanName)) {  
            throw new RuntimeException("[" + beanName + "] 已存在");  
        }  
        BEANS.put(beanName, bean);  
    }  
}  

Spring是注冊(cè)表單例設(shè)計(jì)模式的實(shí)現(xiàn),消除了編程式單例,而且對(duì)代碼是非入侵式。

接下來(lái)讓我們看看在Spring中如何配置單例Bean吧,在Spring容器中如果沒(méi)指定作用域默認(rèn)就是“singleton”,配置方式通過(guò)scope屬性配置,具體配置如下:

<bean  class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/>  

Spring不僅會(huì)緩存單例對(duì)象,Bean定義也是會(huì)緩存的,對(duì)于惰性初始化的對(duì)象是在首次使用時(shí)根據(jù)Bean定義創(chuàng)建并存放于單例緩存池。

3-5.JPG

prototype:

即原型,指每次向Spring容器請(qǐng)求獲取Bean都返回一個(gè)全新的Bean,相對(duì)于“singleton”來(lái)說(shuō)就是不緩存Bean,每次都是一個(gè)根據(jù)Bean定義創(chuàng)建的全新Bean。

GoF原型設(shè)計(jì)模式,指用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。

Spring中的原型和GoF中介紹的原型含義是不一樣的:

  • GoF通過(guò)用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),而Spring容器用Bean定義指定創(chuàng)建對(duì)象的種類(lèi);
  • GoF通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象,而Spring容器根據(jù)Bean定義創(chuàng)建新對(duì)象。

其相同地方都是根據(jù)某些東西創(chuàng)建新東西,而且GoF原型必須顯示實(shí)現(xiàn)克隆操作,屬于侵入式,而Spring容器只需配置即可,屬于非侵入式。

只需指定<bean>標(biāo)簽屬性“scope”屬性為“prototype”即可:

<bean class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/>

Spring管理原型對(duì)象在Spring容器中存儲(chǔ)如圖3-6所示,Spring不會(huì)緩存原型對(duì)象,而是根據(jù)Bean定義每次請(qǐng)求返回一個(gè)全新的Bean:

3-6.JPG

Web應(yīng)用中的作用域

在Web應(yīng)用中,我們可能需要將數(shù)據(jù)存儲(chǔ)到request、session、global session。因此Spring提供了三種Web作用域:request、session、globalSession。

一、request作用域:

表示每個(gè)請(qǐng)求需要容器創(chuàng)建一個(gè)全新Bean。比如提交表單的數(shù)據(jù)必須是對(duì)每次請(qǐng)求新建一個(gè)Bean來(lái)保持這些表單數(shù)據(jù),請(qǐng)求結(jié)束釋放這些數(shù)據(jù)。

二、session作用域:

表示每個(gè)會(huì)話(huà)需要容器創(chuàng)建一個(gè)全新Bean。比如對(duì)于每個(gè)用戶(hù)一般會(huì)有一個(gè)會(huì)話(huà),該用戶(hù)的用戶(hù)信息需要存儲(chǔ)到會(huì)話(huà)中,此時(shí)可以將該Bean配置為web作用域。

三、globalSession:

類(lèi)似于session作用域,只是其用于portlet環(huán)境的web應(yīng)用。如果在非portlet環(huán)境將視為session作用域。

配置方式和基本的作用域相同,只是必須要有web環(huán)境支持,并配置相應(yīng)的容器監(jiān)聽(tīng)器或攔截器從而能應(yīng)用這些作用域,我們會(huì)在集成web時(shí)講解具體使用,大家只需要知道有這些作用域就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容