spring中bean的五種作用域
當通過spring容器創建一個Bean實例時,不僅可以完成Bean實例的實例化,還可以為Bean指定特定的作用域。Spring支持如下5種作用域:
-
singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例
-
prototype:原型模式,每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例
-
request:對於每次HTTP請求,使用request定義的Bean都將產生一個新實例,即每次HTTP請求將會產生不同的Bean實例。只有在Web應用中使用Spring時,該作用域才有效
-
session:對於每次HTTP Session,使用session定義的Bean豆漿產生一個新實例。同樣只有在Web應用中使用Spring時,該作用域才有效
-
globalsession:每個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。典型情況下,僅在使用portlet context的時候有效。同樣只有在Web應用中使用Spring時,該作用域才有效
其中比較常用的是singleton和prototype兩種作用域。對於singleton作用域的Bean,每次請求該Bean都將獲得相同的實例。容器負責跟蹤Bean實例的狀態,負責維護Bean實例的生命周期行為;如果一個Bean被設置成prototype作用域,程序每次請求該id的Bean,Spring都會新建一個Bean實例,然后返回給程序。在這種情況下,Spring容器僅僅使用new 關鍵字創建Bean實例,一旦創建成功,容器不在跟蹤實例,也不會維護Bean實例的狀態。
如果不指定Bean的作用域,Spring默認使用singleton作用域。Java在創建Java實例時,需要進行內存申請;銷毀實例時,需要完成垃圾回收,這些工作都會導致系統開銷的增加。因此,prototype作用域Bean的創建、銷毀代價比較大。而singleton作用域的Bean實例一旦創建成功,可以重復使用。因此,除非必要,否則盡量避免將Bean被設置成prototype作用域。
參考鏈接:Spring中Bean的五個作用域
Spring中的bean是線程安全的嗎?
spring 管理的 bean 的線程安全跟 bean 的創建作用域和 bean 所在的使用環境是否存在競態條件有關,spring 並不能保證 bean 的線程安全。
原型Bean
對於原型Bean,每次創建一個新對象,也就是線程之間並不存在Bean共享,自然是不會有線程安全的問題。
單例Bean
對於單例Bean,所有線程都共享一個單例實例Bean,因此是存在資源的競爭。
如果單例Bean,是一個無狀態Bean,也就是線程中的操作不會對Bean的成員執行查詢以外的操作,那么這個單例Bean是線程安全的。比如Spring mvc 的 Controller、Service、Dao等,這些Bean大多是無狀態的,只關注於方法本身。
spring單例,為什么controller、service和dao確能保證線程安全?
Spring中的Bean默認是單例模式的,框架並沒有對bean進行多線程的封裝處理。
實際上大部分時間Bean是無狀態的(比如Dao) 所以說在某種程度上來說Bean其實是安全的。
但是如果Bean是有狀態的 那就需要開發人員自己來進行線程安全的保證,最簡單的辦法就是改變bean的作用域 把 "singleton"改為’‘protopyte’ 這樣每次請求Bean就相當於是 new Bean() 這樣就可以保證線程的安全了。
有狀態就是有數據存儲功能
無狀態就是不會保存數據
controller、service和dao層本身並不是線程安全的,只是如果只是調用里面的方法,而且多線程調用一個實例的方法,會在內存中復制變量,這是自己的線程的工作內存,是安全的。
所以其實任何無狀態單例都是線程安全的。
參考鏈接:spring中的bean是線程安全的嗎?
