Spring的Bean的作用域
- Singleton:默认的作用域,生成单例对象,生命周期跟SpringIOC容器一样,第一次注入时创建
- Prototype:原型,每次生成新的对象
- Request:每次Http请求创建一个单例对象,那次请求就一直使用这个对象
- Session:同一个会话使用同一个对象,不同会话使用不同对象
- Global-session:所有会话使用同一个实例
说明
Singleton作用域下所有线程使用同一个Bean,因此存在资源竞争问题。
如果单例Bean是无状态的,就是不存储数据,例如Spring mvc 的 Controller、Service、Dao等,就只是执行方法操作而不关注对象本身的状态。因为Controller等每次调用里面的方法JVM都会生成线程私有的栈,因此执行方法是不存在线程不安全的。
如果里面有数据存储,例如private int count = 0; 就表示是有状态的
@Controller
public class controller {
private int count = 0;
@ResponseBody
@GetMapping("/count")
public String addCount(){
count++;
System.out.println("count的值为:"+count);
return "Success";
}
}
发送多个请求,结果是
说明线程不安全,可以把Controller的作用域改为prototype
结果变成线程安全。
如果Bean中有静态变量 ,例如 private static int count = 0;,作用域变为原型也是线程不安全,**这种情况下可以使用ThreadLocal保证线程安全。**当然可以加锁解决变量共享问题。