Spring中的Bean默认都是单例(singleton),Spring中Bean的scope属性有五种类型:
- singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例
- prototype 表示每次获得bean都会生成以新的对象
- request 表示在一次Htttp请求内有效(只适用于web应用)
- session 表示在一个用户会话内有效(只适用于web应用)
- globalSession 表示在全局会话内有效(只适用于web应用)
SpringMVC中Controller类默认Scope是单例,因而在Controller类中使用成员变量时需要注意并发的问题,举例说明:
@Controller
public class ExampleAction {
private int singletonInt=0;
@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/test?data=15 ,得到的结果分别是15 30 45,由此说明Controller是单例
单例的好处也很明显:不用每次创建Controller,减少了对象创建和垃圾收集的时间。
当有多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,各个线程是不会相互影响,举例如下:
@RequestMapping(value = "/sleepdata")
@ResponseBody
public String switcher(HttpServletRequest request, HttpServletResponse response) throws Exception {
String sleep = request.getParameter("sleep");
if (sleep.equals("on")) {
Thread.currentThread().sleep(100000);
return "sleep on";
} else {
return sleep;
}
}
分别发送两个请求,
第一个请求:http://localhost:8080/sleepdata?sleep=on
第二个请求:http://localhost:8080/sleepdata?sleep=test
验证结果:第一个请求发出去以后,本地服务器等待100s,然后返回结果”sleep on”,在本地服务器等待的者100s当中,发送第二个请求,直接返回结果”test”。说明之间的线程是不互相影响的
单例的状态改变:体现为该单例的成员属性值的修改
有状态对象(Stateful Bean):就是有成员变量的对象,可以保存数据,是非线程安全的
无状态对象(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的
Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态
浏览器访问服务器时将会产生一个session,同时会产生多个线程来处理请求,代码示例如下:
@Controller
public class SlemController {
@GetMapping("/slem")
public ResponseEntity<?> slem(HttpServletRequest request) {
return ResponseEntity.ok("SESSIONID " + request.getSession().getId() + " THREAD " + Thread.currentThread().getName());
}
}
分别用Chrome和Firefox访问这个controller,可以得到如下结果:同一个浏览器sessionid都是相同,但是thread不同,由此可以验证SpringMVC的多线程,测试发现,一个session最多创建10个线程,有待查验。