Spring Bean 作用域詳解

在 Spring 中早抠,那些組成應用程序的主體,以及由 Spring IOC 容器所管理的對象募寨,被稱之為 bean。簡單地講森缠,bean 就是由 IOC 容器初始化拔鹰、裝配及管理的對象,除此之外贵涵,bean 就與應用程序中的其他對象沒有什么區(qū)別了列肢,而 bean 的定義以及 bean 相互間的依賴關(guān)系,將通過配置元數(shù)據(jù)來描述宾茂。

Spring 中的 bean 默認都是單例的瓷马,在多線程程序下,這些單例 Bean 是如何保證線程安全的呢跨晴?

例如對于 Web 應用來說欧聘,Web 容器對于每個用戶的請求,都會創(chuàng)建一個單獨的 Sevlet 線程來處理請求端盆,引入 Spring 框架后怀骤,每個 Action 都是單例的,那么對于 Spring 托管的單例 Service Bean焕妙,如何保證其安全呢蒋伦?

答案是:Spring 的單例是基于 BeanFactory,也就是 Spring 容器的焚鹊,單例 Bean 在此容器內(nèi)只有一個痕届,Java 的單例是基于 JVM,每個 JVM 內(nèi)只有一個實例。

在大多數(shù)情況下研叫。單例 bean 是很理想的方案锤窑。不過,有時候系統(tǒng)所使用的類是易變的蓝撇,它們會保持一些狀態(tài)果复,因此重用是不安全的。在這種情況下渤昌,將 class 聲明為單例就顯得不是那么明智了虽抄。因為對象會被污染,重用的時候可能會出現(xiàn)意想不到的問題独柑,所以 Spring 定義了支持多種作用域的 bean迈窟。

bean 的作用域

創(chuàng)建一個 bean 定義,其實質(zhì)是用該 bean 定義對應的類來創(chuàng)建真正實例的 “配方”忌栅。把 bean 定義看成是配方很有意義车酣,它與 class 很類似,只根據(jù)一張 “處方” 就可以創(chuàng)建多個實例索绪,不僅可以控制注入到對象中的各種依賴和配置值湖员,還可以控制該對象的作用域。這樣可以靈活選擇所建對象的作用域瑞驱,而不必在 Java Class 級定義作用域娘摔。如下表所示,Spring Framework 支持五種作用域唤反。

Spring 五種作用域

以上五種作用域中凳寺,request、sessionglobal session 三種作用域彤侍,僅能用在基于 web 的 Spring ApplicationContext 環(huán)境肠缨。

singleton:唯一 bean 實例

當一個 bean 的作用域為 singleton 時,那 Spring IoC 容器中只會存在一個共享的 bean 實例盏阶,并且所有對 bean 的請求晒奕,只要 id 與該 bean 定義相匹配,則只會返回 bean 的同一實例般哼。 singleton 是單例類型 (對應于單例模式)吴汪,就是在創(chuàng)建容器時就同時創(chuàng)建一個該 bean 的對象,不管是否使用蒸眠,不過可以指定 Bean 節(jié)點的 lazy-init="true" 來延遲初始化 bean,這時候杆融,只有在第一次獲取 bean 時才會初始化 bean楞卡,以后每次獲取到的對象都是同一個對象。注意,singleton 作用域是 Spring 中的缺省作用域蒋腮。如果要顯示在 XML 中將 bean 定義成 singleton 淘捡,可以這樣配置:

<bean id="ServiceImpl" class="cn.mariojd.service.ServiceImpl" scope="singleton">

也可以通過 @Scope 注解(還可以顯示指定 bean 的作用范圍)的方式:

@Service
@Scope("singleton")
public class ServiceImpl {

}

prototype:每次請求都會創(chuàng)建一個新的 bean 實例

當一個 bean 的作用域為 prototype,表示一個 bean 的定義對應多個對象實例池摧。prototype 作用域的 bean 會導致每次在對該 bean 請求(將其注入到另一個 bean 中焦除,或者以程序的方式調(diào)用容器的 getBean() 方法)時,都會創(chuàng)建一個新的 bean 實例作彤。prototype 是原型類型膘魄,它在我們創(chuàng)建容器的時候并沒有實例化,而是當我們獲取 bean 的時候才去創(chuàng)建一個對象竭讳,而且每次獲取到的對象都不是同一個對象创葡。

總之,對有狀態(tài)的 bean 應該使用 prototype 作用域绢慢,而對無狀態(tài)的 bean 則應該使用 singleton 作用域灿渴。在 XML 中將 bean 定義成 prototype ,可以這樣配置:

<bean id="account" class="cn.mariojd.DefaultAccount" scope="prototype"/>  
# 或者
<bean id="account" class="cn.mariojd.DefaultAccount" singleton="false"/> 

request:每次 HTTP 請求都會產(chǎn)生新的 bean胰舆,該 bean 僅在當前 HTTP request 內(nèi)有效

request 作用域只適用于 Web 程序骚露,每一次 HTTP 請求都會產(chǎn)生一個新的 bean,同時該 bean 僅在當前 HTTP request 內(nèi)有效缚窿,當請求結(jié)束后棘幸,該對象的生命周期即結(jié)束。在 XML 中將 bean 定義成 request 滨攻,可以這樣配置:

<bean id="loginAction" class=cn.mariojd.LoginAction" scope="request"/>

session:每次 HTTP 請求都會產(chǎn)生新的 bean够话,該 bean 僅在當前 HTTP session 內(nèi)有效

session 只適用于 Web 程序,session 作用域表示該針對每一次 HTTP 請求都會產(chǎn)生一個新的 bean光绕,同時該 bean 僅在當前 HTTP session 內(nèi)有效女嘲。當HTTP session 最終被廢棄的時候,在該 HTTP session 作用域內(nèi)的 bean 也會被銷毀掉诞帐。

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

globalSession:伴隨應用本身的全局作用域

global session 作用域類似于標準的 HTTP session 作用域欣尼,不過僅僅在基于 portlet 的 web 應用中才有意義。Portlet 規(guī)范定義了全局 Session 的概念停蕉,它被所有構(gòu)成某個 portlet web 應用的各種不同的 portlet 所共享愕鼓。在 global session 作用域中定義的 bean ,將被限定于全局 portlet Session 的生命周期范圍內(nèi)慧起。

<bean id="user" class="cn.mariojd.Preferences "scope="globalSession"/>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菇晃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚓挤,更是在濱河造成了極大的恐慌磺送,老刑警劉巖驻子,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異估灿,居然都是意外死亡崇呵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門馅袁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來域慷,“玉大人,你說我怎么就攤上這事汗销∮贪” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵大溜,是天一觀的道長化漆。 經(jīng)常有香客問我,道長钦奋,這世上最難降的妖魔是什么座云? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮付材,結(jié)果婚禮上朦拖,老公的妹妹穿的比我還像新娘。我一直安慰自己厌衔,他們只是感情好璧帝,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著富寿,像睡著了一般睬隶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上页徐,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天苏潜,我揣著相機與錄音,去河邊找鬼变勇。 笑死恤左,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的搀绣。 我是一名探鬼主播飞袋,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼链患!你這毒婦竟也來了巧鸭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤麻捻,失蹤者是張志新(化名)和其女友劉穎蹄皱,沒想到半個月后览闰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芯肤,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡巷折,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了崖咨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锻拘。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖击蹲,靈堂內(nèi)的尸體忽然破棺而出署拟,到底是詐尸還是另有隱情,我是刑警寧澤歌豺,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布推穷,位于F島的核電站,受9級特大地震影響类咧,放射性物質(zhì)發(fā)生泄漏馒铃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一痕惋、第九天 我趴在偏房一處隱蔽的房頂上張望区宇。 院中可真熱鬧,春花似錦值戳、人聲如沸议谷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卧晓。三九已至,卻和暖如春赴捞,著一層夾襖步出監(jiān)牢的瞬間逼裆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工螟炫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留波附,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓昼钻,卻偏偏與公主長得像掸屡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子然评,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容