提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
面试经常会被问到SpringMVC中的Controller是多例还是单例,这下就有点懵了,很多同学会认为Controller是多例吧?其实并不是。
提示:以下是本篇文章正文内容,下面案例可供参考
一、关于SpringMVC的Controller的单例还是多例
根据Tomcat的官网介绍,对于一个浏览器请求,Tomcat会指定某个处理线程,或者新建一个线程,或者在线程池中选取一个空闲的线程去处理。
在Tomcat中,每个servlet都是单例,在SpringMVC中,默认也是单例,Controller亦是如此。
在扩展一个知识点:单例的优缺点。
优点:高并发时,单例可以极大的节省内存资源,提高服务抗压能力。确保每个所有的对象都有访问一个实例。
缺点:多个请求并发会出现竞争访问资源。如果有变化的对象,会导致数据错误。
二、Controller是线程安全吗?
因为Controller默认是单例,所以不是线程安全。
特别需要注意,如果用SpringMVC的Controller时,尽量不要在Controller层使用实例变量,否则会出现线程不安全情况,导致数据逻辑混乱。
代码如下(示例):
package test;
import org.springframework.stereotype.Controller;
@Controller
public class mvc {
private int i = 0;
@RequestMapping("/binbin/addI")
public void addI(){
i++;
System.out.println("i value = "+i);
}
}
第一次访问http://localhost:8080/binbin/addI
第二次再访问http://localhost:8080/binbin/addI
分别得到的答案是1和2.
这明显就不是我们先要的数据。
所以从例子中我们可以看出,所有请求都访问一个Controller时,Controller的私有变量就是线程共享,某个对应的请求修改了这个变量,那后面的请求中只是读到了修改后的值。
解决并发安全的办法
- 尽量不要在Controller中定义私有变量;
- 或者通过注解@Scope(“prototype”).将Controller设置为多例模式