Spring 并发访问的线程安全性问题
首先对于spring的IOC来说,对象是由Spring来帮我们管理,也就是在Spring启动的时候,在Spring容器中,由Spring给我们创建的,Spring会帮我们维护,一般都是单例的,也就是一个对象。
spring生成对象默认是单例的。通过scope属性可以更改为多例。
第一部分:验证Spring生成对象默认是单例的。
下面我们来一个网上的例子验证一下:
- <bean id="singleton" class="java.util.Date" scope="singleton"></bean>
- <bean id="prototype" class="java.util.Date" scope="prototype"></bean>
- package test;
- import java.util.Date;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import com.opensymphony.xwork2.ActionContext;
- public class TestScope {
- public static void main(String[] args) {
- ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext-web.xml");
- Date s1=(Date)context.getBean("singleton");
- Date p1=(Date)context.getBean("prototype");
- Date s2=(Date)context.getBean("singleton");
- Date p2=(Date)context.getBean("prototype");
- System.out.println("单例:"+(s1==s2));
- System.out.println("非单例:"+(p1==p2));
- }
- }
输出结果:
结果
单例:true
非单例:false
注:复合数据类型的“== ”对比的是内存中存放的地址,所以此处我们采用“==”去对比
因为object中的equals初始行为是比较内存中的地址,但在一些类库中被覆盖掉了如(String,Integer,Date等)
第二部分:SpringMVC和Struts2中是并发访问否会存在线程安全问题。
对于使用过SpringMVC和Struts2的人来说,大家都知道SpringMVC是基于方法的拦截,而Struts2是基于类的拦截。
对于Struts2来说,因为每次处理一个请求,struts就会实例化一个对象;这样就不会有线程安全的问题了;
而Spring的controller默认是Singleton的,这意味着每一个request过来,系统都会用原有的instance去处理,这样导致两个结果:
一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。
当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义实例变量。
如:
- public class Controller extends AbstractCommandController {
- protected Company company;
- protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,Object command,BindException errors) throws Exception {
- company = ................;
- }
- }
解决方案:
有几种解决方法:
1、在Controller中使用ThreadLocal变量
2、在spring配置文件Controller中声明 scope="prototype",每次都创建新的controller
所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。
例如:
- @Controller
- @RequestMapping("/fui")
- public class FuiController extends SpringController {
- //这么定义的话就是单例
- @Controller
- @Scope("prototype")
- @RequestMapping("/fui")
- public class FuiController extends SpringController {
- //每次都创建
第三部分:springMVC与struts2的区别。
下面是从网络上摘抄的一段对比,大家可以看看
1. 机制:spring mvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同。
2. 性能:spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。
3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。
4. 设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。
5. intercepter的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。
6. 另外,spring3 mvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便,只需一个注解@ResponseBody ,然后直接返回响应文本即可。
总结:
这样也说明了SpringMVC还有Servlet都是方法的线程安全,所以在类方法声明的私有或者公有变量不是线程安全的,而struts2的确实是线程安全的。
第四部分:那么对于Struts2+Spring来管理注入的时候呢?
Struts2它是多实例的,对于每个请求都会生成1个实例,spring默认是单实例的(下面针对Struts与Spring集成的两种方式分别来介绍struts2和spring的两种整合方式)
一:对于无Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式,需要在spring的action Bean中加业务逻辑控制器类配scope="prototype"。
- <bean id="user" class="modle.User" scope="prototype"></bean>
二:对于有Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式:反编译StrutsSpringObjectFactory以及相关的代码才发现,如果在struts action的配置文件中<action name=".." class=".."/>中class写的如果是完整的包名和类名的话就是struts创建action对象,也就是多实例的;
总结:如果是spring配置文件中的 bean的名字的话就是spring创建,那么单实例还是多实例就由spring的action Bean中的业务逻辑控制器类是否配置为scope=”prototype”,有就是多实例的,没有就是单实例的,顺序是先从spring中找,找不到再从struts配置文件中找。
Spring 并发访问的线程安全性问题的更多相关文章
- Spring并发访问的线程安全性问题
Spring并发访问的线程安全性问题 http://windows9834.blog.163.com/blog/static/27345004201391045539953/ 由于Spring MVC ...
- (转)Spring并发访问的线程安全性问题(高度总结)
下面的记录对spring中并发的总结.理论分析参考Spring中Singleton模式的线程安全,建议先看 spring中的并发访问题: 我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下 ...
- Spring 是如何解决并发访问的线程安全性问题的
springmvc的controller是singleton的(非线程安全的),这也许就是他和struts2的区别吧!和Struts一样,Spring的Controller默认是Singleton的, ...
- Springmvc 并发访问的线程安全性问题
首先对于spring的IOC来说,对象是由Spring来帮我们管理,也就是在Spring启动的时候,在Spring容器中,由Spring给我们创建的,Spring会帮我们维护,一般都是单例的,也就是一 ...
- 【Java并发.2】线程安全性
要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享(Shared)和可变的(Mutable)状态的访问. “共享”意味着变量可以由多个线程同时访问,而“可变”则意味着变量的值在其生 ...
- Java并发编程 (四) 线程安全性
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.线程安全性-原子性-atomic-1 1.线程安全性 定义: 当某个线程访问某个类时,不管运行时环境 ...
- Spring 中的 bean线程安全性分析
首先:Spring 中的 bean不是线程安全的 Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但 ...
- JAVA并发编程之线程安全性
1.一个对象是否是线程安全的,取决于它是否被多个线程访问.想要使得线程安全,需要通过同步机制来协同对对象可变状态的访问. 2.修复多线程访问可变状态变量出现的错误:1.程序间不共享状态变量 2.状态变 ...
- Semaphore可以控制并发访问的线程个数
public class SemaphoreTest { //信号量,只允许 3个线程同时访问 ); public static void main(String[] args) { Executor ...
随机推荐
- [leetcode-583-Delete Operation for Two Strings]
Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 t ...
- 【LeetCode】49. Group Anagrams
题目: Given an array of strings, group anagrams together. For example, given: ["eat", " ...
- MaintainableCSS 《可维护性 CSS》 --- ID 篇
ID 从语法上讲,当只有一个实例时,我们应该使用一个ID.当有多个时,我们应该使用一个 class. 但是,ID 作用的优先级高于 class ,在我们想覆盖一个样式的时候,这就会导致问题. 为了演示 ...
- 使用matplotlib快速绘图
matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表.让我们先来看一个简单的例子: # -*- coding: utf-8 -*- import num ...
- java基础系列--Calendar类
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/7136575.html 1.Calendar概述 Java官方推荐使用Calendar来替换 ...
- spring注解@service("service")括号中的service有什么用
相当于 xml配置中得 bean id = service 也可以不指定 不指定相当于 bean id = com. service.service 就是这个类的全限定名 好处是:同一个接口可以有多个 ...
- js通过Date获取日期
获取当前系统时间 var myDate = new Date();//获取系统当前时间 获取特定格式日期 myDate.getYear(); //获取当前年份(2位) myDate.getFullYe ...
- POJ 3683 Priest John's Busiest Day / OpenJ_Bailian 3788 Priest John's Busiest Day(2-sat问题)
POJ 3683 Priest John's Busiest Day / OpenJ_Bailian 3788 Priest John's Busiest Day(2-sat问题) Descripti ...
- wampserver2.5局域网IP访问配置
wampserver2.5集成环境的安装和使用就不多说了,网上有很多教材.安装好后找到apache的配置文件httpd.conf.默认位置是: swap安装目录\wamp\bin\apache\apa ...
- ps_cc切片
web前端开发的工作流程的第一步就是根据ui给的psd来还原设计图样貌. 可是一打开满屏的参考线.这时我们可以alt+v+d清空参考线 这时可以按alt+鼠标拖放图片.同时也可以按F进入半屏和匀速连按 ...