Spring中的Bean是線程安全的嗎?為什么?
????????答案:不是。
????????因為SpringIOC容器本身沒有提供Bean的線程安全策略,所以Spring容器中的Bean本身不具備線程安全的特性,現(xiàn)在結合具體的作用域(scope)去研究。
Spring的Bean作用域scope類型(五種):
? ? ? ? a.singleton(單例):默認作用域,SpringIOC中僅存在一個Bean實例,以單例Bean的方式存在。
? ? ? ? b.prototype(原型):每次從容器中getBean()時,都返回一個新的實例。等于執(zhí)行new Bean()。
? ? ? ? c.request(請求):每次Http請求創(chuàng)建一個新對象。
? ? ? ? d.session(會話):同一個會話共享一個實例,不同會話使用不同實例。
? ? ? ? e.global-session(全局會話):所有會話共享一個實例。
request(請求)、session(會話)、global-session(全局會話):
? ??????**\color{red}{僅僅適用于WebApplicationContext環(huán)境下。}**
????????$\color{red}{紅色字}$
線程安全這個問題,從常用的單例和原型Bean分別說明:
singleton(單例)Bean:
? ? ? ? 所有線程都共享一個單例Bean,因此是存在資源的競爭。
? ? ? ? 如果單例Bean是無狀態(tài)的,也就是線程之間的操作不會對Bean的成員執(zhí)行查詢以外的操作,那么這個單例Bean是線程安全的。比如:Spring Mvc、Controller、Service、Dao等,這些Bean大多數(shù)是無狀態(tài)的,只需要關注方法本身即可。
prototype(原型)Bean:
????????每個線程都創(chuàng)建一個新的對象,線程之間不存在Bean的共享,自然不存在線程安全的問題。
Spring中Bean是默認單例的,為什么Controller、Service、和Dao能保證線程安全?
? ? ? ? Spring 中Bean默認是單例模式的,框架并沒有對Bean進行多線程的封裝處理。? ? ? ?
? ? ? ? Controller、Service和Dao本身并不是線程安全的,Java虛擬機棧是線程私有的,它的生命周期與線程相同,跟隨線程結束而結束。
? ? ? ? 但是,如果Bean是有狀態(tài)的,就需要開發(fā)人員自己來進行線程安全的保證,最簡單的方法就是改變Bean的作用域把“singleton”改為“prototype",這樣每次請求Bean都相當于new Bean(),問題解決。
tips:
? ? ? ? 有狀態(tài)就是有存儲數(shù)據(jù)的功能。
? ? ? ? 無狀態(tài)就是不會存儲數(shù)據(jù)。