Spring学习(十五)——单例Bean的线程安全(Web开发)

目录

 

前言

问题

验证

为什么如此设计

由此出现的另一个问题


前言

最近在做一个网站的项目,考虑到Spring的Bean默认为单例,会不会出现请求排队的现象,于是有了这篇博客(业务代码真的很无聊呀..........

问题

Spring的Bean默认是单例,在接收到请求后,tomcat是创建一个线程去处理对应请求的,此时单例Bean就相当于临界资源,临界资源最典型的问题就是改值问题,为了防止此问题,我们通常会用上锁,而锁的存在会影响到效率,创建多线程就是为了提高处理速度,而锁的出现把原来的并发强行变为了串行(在这个问题中),那么spring会不会对对象上锁呢?答案是不会

验证

项目结构如下:

为springboot项目,所以文件很少

ControllerTemp:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@ResponseBody
//实验结果,支持多线程的同步执行,不会上锁
public  class ControllerTemp {
	
	@SuppressWarnings("static-access")
	@RequestMapping("/hello")
	public String deal(int time) {
		try   
		{   
		Thread.currentThread().sleep(time);//毫秒
		}   
		catch(Exception e){} 
		    return "hello word";
	}
}

启动类代码不贴了,测试url:

1、http://localhost:8080/hello?time=100000000
2、http://localhost:8080/hello?time=100

先请求第一个url,后请求第二个,如果bean是上锁的,第二个url肯定很快返回,但实际测试是第二个url一下就返回了

为什么如此设计

谈谈我的理解,在web开发中,会出现DAO层、server层、controller层,DAO层负责与数据库的交互,server层负责调用DAO层获得数据,controller层通过调用server层进行业务流程,为什么要分这么多层?这在一定程度上是一种解耦,使代码易于维护,类的功能变得比较清晰,这三层的核心都是操作数据库,DAO、server就不说了,controller层调用server也是间接操作数据库,在数据库设计比较合理的情况下,这三层基本不需要也不应该(与用户相关的信息不应该存储在这三层中的属性)设计额外的属性,基于这个理念,改值问题也就不会存在了,如果spring对单例上锁,为了提高效率,我们可能会将Bean的Scop改为session,访问人数多时,创建的对象也会增多,花费的垃圾回收时间也相应增加

由此出现的另一个问题

从之前的讨论中,我们知道与用户相关的信息不应该保存在这三层之中,那么与用户相关的信息应该保留在哪呢?有两种选择,一种是cookie,一种是session,如果我们使用session,可能会出现问题两个问题,一、session对象的生命周期比单例Bean的短二、Server层、Controller层是单例,如果将session对象作为依赖注入到Server层,之后都是对同一个session操作,并且可能出现空指针的情况,怎么办?不怕不怕,可以使用AOP代理:Bean的scopes

猜你喜欢

转载自blog.csdn.net/dhaiuda/article/details/82555349