經典面試題——Spring 的 Controller 是單例還是多例?

我們經常說單例還是多例,那麼究竟他們不同的根源在哪?

或者說我們應該從哪一方面具體地去理解了,至於這個問題,今天來分享一波

答案:

先直接上答案吧,Spring的Controller預設是單例的。所以,我們不要使用非靜態的成員變數,否則會發生執行緒安全問題,導致資料邏輯混亂。正因為單例所以不是執行緒安全的。

我們下面來簡單的驗證下:

經典面試題——Spring 的 Controller 是單例還是多例?

我們首先訪問 http://localhost:8080/testScope,得到的答案是1;

然後我們再訪問 http://localhost:8080/testScope2,得到的答案是 2。

得到的不同的值,這是執行緒不安全的

接下來我們再來給controller增加作用多例 @Scope(“prototype”)

經典面試題——Spring 的 Controller 是單例還是多例?

我們依舊首先訪問 http://localhost:8080/testScope,得到的答案是1;

然後我們再訪問 http://localhost:8080/testScope2,得到的答案還是1。

經典面試題——Spring 的 Controller 是單例還是多例?

相信大家不難發現 :

單例是不安全的,會導致屬性重複使用

解決方案:

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。

免費學習資料包、技術大佬答疑群

私聊源寶即可獲得哦~