Spring 之 Scope篇

摘自《Spring 解密》

scope用來聲明IOC容器中的對象應該處的限定場景或者說該對象的存活空間,即在IOC容器在對象進入相應的scope之前,生成並裝配這些對象,在該對象不再處於這些scope的限定之後,容器通常會銷燬這些對象。打個比方吧!我們都是處在社會(容器)中,如果把中學教師作爲一個類定義,那麼當容器初始化這些類之後,中學教師只能侷限在中學這個場景中,中學,就可以看做中學教師的scope。

Spring容器最初提供了兩種bean的scope類型:singleton和prototype,但發佈2.0之後,又引入了另外三種scope類型,即request,session和global session類型。不過這三種類型有所限制,只能在web應用中使用,也就是說,只有在支持web應用的ApplicationContext中使用這三個scope纔是合理的。

可以使用bean的singleton或scope屬性來指定相應對象的scope,其中,scope屬性只能在XSD格式的文檔生命中使用,類似於如下代碼所演示的形式:

DTD:

<bean id ="mockObject1" class="..." singleton="false" />

XSD:

<bean id ="mockObject1" class="..." scope="prototype" />

注意:這裏的singleton和設計模式裏面的單例模式不一樣,標記爲singleton的bean是由容器來保證這種類型的bean在同一個容器內只存在一個共享實例,而單例模式則是保證在同一個Classloader中只存在一個這種類型的實例。

1. singleton

singleton類型的bean定義,在一個容器中只存在一個實例,所有對該類型bean的依賴都引用這一單一實例,這就好像每個幼兒園都會有一個滑梯一樣,這個幼兒園的小朋友共同使用這一個滑梯,而對於幼兒園容器來說,滑梯就是一個singleton的bean。

此外,singleton類型的bean定義,從容器啓動,到他第一次被請求而實例化開始,只要容器不銷燬或退出,該類型的bean的單一實例就會一直存活。

通常情況下,如果你不指定bean的scope,singleton便是容器默認的scope,所以,下面三種配置,形式實際上達成的是同樣的效果:

DTD or XSD:

<bean id ="mockObject1" class="..." />

DTD:

<bean id ="mockObject1" class="..." singleton="true" />

XSD:

<bean id ="mockObject1" class="..." scope="singleton" />

2 prototype

scope爲prototype的bean,容器在接受到該類型的對象的請求的時候,會每次都重新生成一個新的對象給請求方,雖然這種類型的對象的實例化以及屬性設置等工作都是由容器負責的,但是隻要準備完畢,並且對象實例返回給請求方之後,容器就不在擁有當前對象的引用,請求方需要自己負責當前對象後繼生命週期的管理工作,包括該對象的銷燬。也就是說,容器每次返回請求方該對象的一個新的實例之後,就由這個對象“自生自滅”了。

讓我們繼續幼兒園的比喻,我們今天要分蘋果了!將蘋果的bean的scope屬性聲明爲prototype,在每個小朋友領取蘋果的時候,我們都是發一個新的蘋果給他,發完之後,小朋友愛怎麼吃就怎麼吃,愛什麼時候吃什麼時候吃,但是注意吃完要把果核扔到垃圾箱哦!對於那些不能共享使用的對象類型,應該將其定義的scope設爲prototype,通常,聲明爲prototype的的bean,都是一些有狀態的,比如保存爲每個顧客信息的對象。

可以用一下方式定義prototype類型的bean:

DTD:

<bean id ="mockObject1" class="..." singleton="false" />

XSD:

<bean id ="mockObject1" class="..." scope="prototype" />

3 request ,session和global session

這三個類型是spring2.0之後新增的,他們不像singleton和prototype那麼通用,因爲他們只適用於web程序,通常是和XmlWebApplicationContext共同使用,將在第6章詳細討論,這裏簡單介紹。

request:

<bean id ="requestPrecessor" class="...RequestPrecessor" scope="request" />

Spring容器,即XmlWebApplicationContext 會爲每個HTTP請求創建一個全新的RequestPrecessor對象,當請求結束後,,該對象的生命週期即告結束。當同時有10個HTTP請求進來的時候,容器會分別針對這10個請求創建10個全新的RequestPrecessor實例,且他們相互之間互不干擾,從不是很嚴格的意義上說,request可以看做prototype的一種特例,除了場景更加具體之外,語意上差不多。

session:

對於web應用來說,放到session中最普遍的就是用戶的登錄信息,對於這種放到session中的信息,我們我們可以使用如下形式的制定scope爲session:

<bean id ="userPreferences" class="...UserPreferences" scope="session" />

Spring容器會爲每個獨立的session創建屬於自己的全新的UserPreferences實例,他比request scope的bean會存活更長的時間,其他的方面真是沒什麼區別。

global session:

<bean id ="userPreferences" class="...UserPreferences" scope="globalsession" />

global session只有應用在基於porlet的web應用程序中才有意義,他映射到porlet的global範圍的session,如果普通的servlet的web 應用中使用了這個scope,容器會把它作爲普通的session的scope對待。

(我只是聽說過porlet這個詞,好像是和servlet類似的一種java web技術,大家以後遇到的時候可以搜一下!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章