Spring 的 Bean 默认都是单例的,某些情况下,单例是并发不安全的,以 Controller
举例,问题根源在于,我们可能会在 Controller
中定义成员变量,如此一来,多个请求来临,进入的都是同一个单例的 Controller
对象,并对此成员变量的值进行修改操作,因此会互相影响,无法达到并发安全(不同于线程隔离的概念,后面会解释到)的效果。
首先来举个例子,证明单例的并发不安全性:
@Controller
public class HomeController {
private int i;
@GetMapping("testsingleton1")
@ResponseBody
public int test1() {
return ++i;
}
}
多次访问此 url,可以看到每次的结果都是自增的,所以这样的代码显然是并发不安全的。
如何解决呢?
我们为了让无状态的海量 HTTP 请求之间不受影响,我们可以采取以下几种措施:
1、单例变原型
对 web 项目,可以 Controller
类上加注解 @Scope("prototype")
或 @Scope("request")
,对非 web 项目,在 Component
类上添加注解 @Sco