SpringMVC Controller 单例 多例

对于SpringMVC 的Controller单例还是多例、下面举例说明:
第一次:类是多例,类里包含一个普通属性,一个静态属性


   

结果:普通属性:0.............静态属性:0
普通属性:0.............静态属性:1
普通属性:0.............静态属性:2
普通属性:0.............静态属性:3
所以说:对于多例情况普通属性时不会共用的,不会产生影响,对于静态属性会去共用这个属性。


第二次:将类改为多例、任然包好一个普通属性与一个静态属性


结果:普通属性:0.............静态属性:0
普通属性:1.............静态属性:1
普通属性:2.............静态属性:2
普通属性:3.............静态属性:3
所以说:对于单例情况普通属性和静态属性都会被共用。


第三次:去掉@Scope注解、任然包含一个普通属性与一个静态属性


结果:普通属性:0.............静态属性:0
普通属性:1.............静态属性:1
普通属性:2.............静态属性:2
普通属性:3.............静态属性:3
所以说:springmvc默认是单例的。
另外在其他方法里面打印



输出的结果是:其他方法访问:普通属性:8............静态属性:8
     
跳到别的方法里面也并不会去取初始值,而是再去共用这个属性。

总结:尽量不要在Controller中定义属性,如果有特殊情况一定要定义属性的时候,那么就在类上面加注解@Scope(prototype)改为多例模式。以前Struts2是基于类的属性进行的,定义属性可以整个类通用,所以默认是多例,不然多线程访问肯定是共用类里面的属性值的,当然肯定就不是安全的。但是SpringMVC是基于方法开发的,都是用形参接收值,一个方法结束了,参数就销毁了,多线程访问都会有一块内存空间产生,里面的参数也是不会共用的,所以SpringMVC默认使用单例模式。所以在Controller类里面不适合定义属性,只要Controller里面不定义属性,那么单例是完全安全的,SpringMVC这样设计的主要的原因是为了提高程序的性能和以后维护值针对业务的维护就行,要是Struts的属性定义多了,都不知道那个方法用了这个属性,对以后程序的维护还是很麻烦的。

最佳实践:

1、不要在controller中定义成员变量。

2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope("prototype"),将其设置为多例模式。

首先我们知道Spring 中controller、service、dao都为单例模式(注:默认状态)。

成员方法也是共享的,为什么就不会出现问题呢?
==================================================
java 里,每个线程都有自己独享的空间,也就是栈内存。线程在调用方法的时候,会创建一个栈帧。也就是说调用一个方法的时候,也就是一个栈帧的入栈过程,该方法执行完毕,栈帧也就出栈了。
换句话讲,成员方法对于每个线程事实上是私有的,而不是你表面看上去的那样是 "共享" 的。

那么为什么成员变量会出问题呢?
==================================================
如你所知道的,每个新建对象都存放在堆中,每个持有该对象引用的线程,都可以访问到它(只要你有那个权限)。
这也就是说,成员变量对于每个线程,事实上是共享的。

原文地址:https://www.cnblogs.com/jtlgb/p/9447701.html