spring 作用域现象

        今天在看spring 源码书籍时突然想到,平常写controller类从来没有加上作用域过,那么默认的作用域应该是singleton了,也就是单列,只创建一个类对象在IOC容器中。

        那么假如我在一个controller中定义一个局部变量,每次访问这个局部变量会改变么?测试代码如下所示,

@Slf4j
@RestController
@RequestMapping(value = "/test")
public class TestController {

	private int index = 0;

	@ApiOperation(value = "测试作用域")
	@RequestMapping(value = "/testBeanScope", method = RequestMethod.GET)
	public int testBeanScope(String action) {
				System.out.println("contrller:"+action+"---"+index);
		index++;

		return index;
	}
}

        答案是会改变,因为是单例,所以我无论用两个浏览器请求,还是一个浏览器两个Tab请求,这个Index都是返回上一次请求相加后的结果,

        第一次请求,返回1,

        第二次请求,返回2,

        第三次请求,返回3······

        随后有改变了作用域,加上@Scope这个注解,这样每一次返回都是1,也就是说每次请求都会创建一个新的实例。

@Scope(scopeName ="request")

        随后又想,如果不同的作用域下,每次用不同的浏览器访问或者同一个浏览器不同Tab页访问同一个URL,这两次访问会不会被影响呢?

        实验代码类如下:

long startTime = System.currentTimeMillis();
		try {
			if (index % 2 == 0)
				Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		long endTime = System.currentTimeMillis();
		long second = (endTime-startTime)/1000;

		System.out.println("contrller:"+action+"---"+index+"  耗时:"+second);
		index++;

     

        下面是我的一些实验数据,

两个浏览器同时请求   @Scope(scopeName ="session")  

第一次同时点击
contrller:frist---0   耗时:10
contrller:third---0   耗时:10

第二次同时点击
contrller:third---1   耗时:0
contrller:frist---1   耗时:0

第三次单独点击第一个浏览器
contrller:frist---2   耗时:10

第四次同时点击
contrller:frist---3   耗时:0
contrller:third---2   耗时:10

         结论: session作用域下,两个不同的浏览器之间不会被影响。

一个浏览器两个TAB   @Scope(scopeName ="session")

第一次同时点击
contrller:frist---0   耗时:10
contrller:second---0  耗时:10
第二次单独点击第一个Tab
contrller:frist---1   耗时:0
第三次同时点击
contrller:frist---2   耗时:10
contrller:second---3  耗时:10(同第一个Tab一起返回值)

        可以看到第三次点击时,second=3这个应该不受Thread.sleep影响,应该离刻返回,但是依旧需要等待first这个Tab页结束。        

        结论: session作用域下,同一浏览器下两个Tab页会被影响。

        为了验证是否作用域会对controller处理请求有影响,所以又将此controller的作用域改变为application,如下所示,

两个浏览器  @Scope(scopeName ="application")

第一次同时点击    
contrller:frist---0  耗时:10
contrller:third---1  耗时:10

        按照代码来看应该是third=1没有睡眠10秒,但是依旧10秒后返回,所以作用域有可能对访问controller造成影响。

两个浏览器    @Scope(scopeName ="singleton")

第一次同时点击
contrller:frist---0  耗时:10
contrller:third---1  耗时:10    
    结果同@Scope(scopeName ="application")

一个浏览器两个TAB  @Scope(scopeName ="prototype")

第一次同时点击
contrller:frist---0  耗时:10
contrller:second---0  耗时:10    
第二次同时点击
contrller:frist---0  耗时:10
contrller:second---0  耗时:10

两个浏览器  @Scope(scopeName ="prototype")

第一次同时点击
contrller:frist---0  耗时:10
contrller:third---0  耗时:10    

补充知识:

singleton

整个spring容器中只会存在一个bean实例,通过容器多次查找bean的时候(调用BeanFactory的getBean方法或者bean之间注入依赖的bean对象的时候),返回的都是同一个bean对象,singleton是scope的默认值,

prototype

如果scope被设置为prototype类型的了,表示这个bean是多例的,通过容器每次获取的bean都是不同的实例,每次获取都会重新创建一个bean实例对象。

request

当一个bean的作用域为request,表示在一次http请求中,一个bean对应一个实例;对每个http请求都会创建一个bean实例,request结束的时候,这个bean也就结束了

session

session级别共享的bean,每个会话(可以理解为第一次浏览器连接服务器)会对应一个bean实例,不同的session对应不同的bean实例

application

全局web应用级别的作用于,也是在web环境中使用的,一个web应用程序对应一个bean实例,通常情况下和singleton效果类似的,不过也有不一样的地方,singleton是每个spring容器中只有一个bean实例,一般我们的程序只有一个spring容器,但是,一个应用程序中可以创建多个spring容器,不同的容器中可以存在同名的bean,但是sope=aplication的时候,不管应用中有多少个spring容器,这个应用中同名的bean只有一个。 

         另外还有一个globalSession,同singleton和prototype差不多。

        以前写controller这种接口从来都没有想过作用域,一直默认是单例,也就是说如果代码里面很耗时,那么也就意味着别人访问还得等前面一个人访问完才行。

        还有比如单例中,在service类中定义了一个成员变量作为计数器,那么这相当于一个全局变量了,每一次访问其实都会对别人的请求造成影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值