我們經常說單例還是多例,那麼究竟他們不同的根源在哪?
或者說我們應該從哪一方面具體地去理解了,至於這個問題,今天來分享一波
答案:
先直接上答案吧,Spring的Controller預設是單例的。所以,我們不要使用非靜態的成員變數,否則會發生執行緒安全問題,導致資料邏輯混亂。正因為單例所以不是執行緒安全的。
我們下面來簡單的驗證下:
我們首先訪問 http://localhost:8080/testScope,得到的答案是1;
然後我們再訪問 http://localhost:8080/testScope2,得到的答案是 2。
得到的不同的值,這是執行緒不安全的
接下來我們再來給controller增加作用多例 @Scope(“prototype”)
我們依舊首先訪問 http://localhost:8080/testScope,得到的答案是1;
然後我們再訪問 http://localhost:8080/testScope2,得到的答案還是1。
相信大家不難發現 :
單例是不安全的,會導致屬性重複使用
解決方案:
1、
一般不要在controller中定義成員變數,當然靜態成員變數,我們知道本身就是共享的。
2、
萬一必須要定義一個非靜態成員變數時候,那就必須要透過註解
@Scope(“prototype”)
,將其設定為多例模式。
3、
或者我們可以在Controller中使用ThreadLocal執行緒隔離,把變數儲存在對應的執行緒中。
補充說明
SpringBean作用域有以下5個:
1、
singleton:單例模式,當spring建立applicationContext容器的時候,spring會欲初始化所有的該作用域例項,加上 lazy-init 就可以避免預處理;
2、
prototype:原型模式,每次透過getBean獲取該bean就會新產生一個例項,建立後spring將不再對其管理;
3、
request:搞web的大家都應該明白request的域了吧,就是每次請求都新產生一個例項;
4、
session: 每次會話,只要是同一個會話,就使用同一個例項;
5、
global session: 全域性的web域,類似於servlet中的application。
免費學習資料包、技術大佬答疑群
私聊源寶即可獲得哦~