SpringMVC 或 SpringBoot 默認是單例模式(Singleton),多個請求是訪問的同一個方法,是如何實現線程安全的?


SpringMVC Controller默認情況下是Singleton(單例)的,當request過來,不用每次創建Controller,會用原來的instance去處理。那么當多個線程調用它的時候,會不會發生線程不安全呢?

1、先說明下 Controller默認情況 單例的問題:

使用Spring MVC有一段時間了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是因為線程安全問題,對於Spring MVC中bean默認都是(singleton)單例的,那么用@Controller注解標簽注入的Controller類是單例實現的?

測試結果發現spring3中的controller默認是單例的,若是某個controller中有一個私有的變量i,所有請求到同一個controller時,使用的i變量是共用的,即若是某個請求中修改了這個變量a,則,在別的請求中能夠讀到這個修改的內容。 若是在@Controller之前增加@Scope(“prototype”),就可以改變單例模式為多例模式

以下是測試步驟,代碼與結果.

1. 如果是單例類型類的,那么在Controller類中的類變量應該是共享的,如果不共享,就說明Controller類不是單例。以下是測試代碼:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
 
import  org.springframework.stereotype.Controller;
import  org.springframework.web.bind.annotation.RequestMapping;
import  org.springframework.web.bind.annotation.ResponseBody;
@Controller
public  class  ExampleAction {
     private  int  singletonInt= 1 ;
      @RequestMapping (value =  "/test" )
      @ResponseBody
      public  String singleton(HttpServletRequest request,
              HttpServletResponse response)  throws  Exception {
          String data=request.getParameter( "data" );
          if (data!= null &&data.length()> 0 ){
              try {
               int  paramInt= Integer.parseInt(data);
              singletonInt = singletonInt + paramInt;
              }
              catch (Exception ex){
                  singletonInt+= 10 ;
              }
          } else {
              singletonInt+= 1000 ;
          }
          return  String.valueOf(singletonInt);
     }
}

分別三次請求: http://localhost:8080/example/test.do?data=15

得到的返回結果如下。

第一次: singletonInt=15

第二次: singletonInt=30

第三次: singletonInt=45

從以上結果可以得知,singletonInt的狀態是共享的,因此Controller是單例的。

 

2、對別Struts與springmvc對比

Struts2          :默認prototype,Struts2 是基於類的,處於線程安全的考慮,采用了prototype模式,也就是說每次請求都會新建一個類來處理,自然就沒有線程安全問題了,每次請求的類和數據都是單獨的。

Springmvc   :默認singleton 單例模式,Springmvc   是基於方法的,同一個url的請求是同一個實例處理的。每次請求都會把請求參數傳遞到同一個方法中,此時如果類里面有成員變量,那么這個變量就不是線程安全的了(例如上面的例子  private int singletonInt=1;  這個變量如果想線程安全則可以用ThreadLocal)。

在類中沒有成員變量的前提下則是線程安全的。

 

參考:https://zhuanlan.zhihu.com/p/103171449

https://blog.csdn.net/sinat_30474567/article/details/64924927

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM