SpringMVC中Controller默認情況下是單例模式(可通過@Scope(value="prototype")設置爲多例)
先來看一下默認情況下:
@Controller
@RequestMapping(value = "/springTest")
public class SpringMvcController
{
public Map<String,Object> hashMap = new HashMap<String,Object>();
@RequestMapping(value="methodA")
@ResponseBody
public String methodA(String type) throws InterruptedException
{
hashMap.put("1", "張三");
return "success";
}
@RequestMapping(value="methodB")
@ResponseBody
public Map<String,Object> methodB(HttpServletRequest request) throws InterruptedException
{
hashMap.put("2", "李四");
hashMap.put("3", "王五");
return hashMap;
}
}
我們先請求methodA(),返回"success" ,然後請求methodB()返回結果是:
然後設置爲多例模式:
@Controller
@RequestMapping(value = "/springTest")
@Scope(value="prototype")
public class SpringMvcController
{
public Map<String,Object> hashMap = new HashMap<String,Object>();
@RequestMapping(value="methodA")
@ResponseBody
public String methodA(String type) throws InterruptedException
{
hashMap.put("1", "張三");
return "success";
}
@RequestMapping(value="methodB")
@ResponseBody
public Map<String,Object> methodB(HttpServletRequest request) throws InterruptedException
{
hashMap.put("2", "李四");
hashMap.put("3", "王五");
return hashMap;
}
}
多例模式下先請求methodA(),然後請求methodB()我們看到返回結果是:
通過對比發現默認情況下(單例模式)我們多次請求的話,成員變量拿到的是相同的一個(因爲請求methodB時,在methodA中put()進去的值也返回了),而多例模式下拿到的是不同的變量(返回的僅僅是methodB()中put()進去的值)。
那麼如果多個線程請求同一個Controller類中的同一個方法,線程是否會堵塞呢?
我們分別發送兩次請求到methodA():
http://127.0.0.1:8080/auth/springTest/methodA?type=1
http://127.0.0.1:8080/auth/springTest/methodA?type=2
@Controller
@RequestMapping(value = "/springTest")
public class SpringMvcController
{
@RequestMapping(value="methodA")
@ResponseBody
public String methodA(String type) throws InterruptedException
{
if(type.equals("1"))
{
TimeUnit.SECONDS.sleep(60);//設置等待60秒
return type;
}else
{
return type;
}
}
}
在type等於1時設置方法等待60秒後再飯後,在這60秒內我們發送第二次請求,得到結果是:2
說明兩次請求的線程之間並沒有影響。
那麼SpringMVC默認不是單例模式嗎,爲什麼沒有影響呢?
1、spring單例模式是指,在內存中只實例化一個類的對象
2、類的變量有線程安全的問題,就是有get和set方法的類成員屬性。執行單例對象的方法不會有線程安全的問題
因爲方法是磁盤上的一段代碼,每個線程在執行這段代碼的時候,會自己去內存申請臨時變量