先看这么一段代码:

@Service
public class AccountService {
private String message; public void foo1() {
if (true) {
this.message = "a";
} else {
this.message = "b";
}
} public void foo2() {
// 改动this.message的代码...
// ... ...
}
}

假设你打算在@Controller里这么调用AccountService :

accountService.foo1();
model.addAttribute(accountService.getMessage());

那么就有线程安全的危急了。

问题原因

在Spring中。bean的默认scope是singleton,也就是说容器中仅仅有一个bean的实例。而在Java Web环境中,webserver会为每个请求创建一个线程来处理它。这样一来。在@Controller中调用@Service bean的方法就会导致有多个线程在运行@Service方法。比如线程A在运行foo1()方法,线程B在运行foo2()方法。

那么问题来了,多个线程同一时候读写message成员变量。就可能让getMessage()方法返回错误的值


解决方法

1. 将@Service bean的scope改为 "request",即:
@Service
@Scope("request")
public class AccountService {
private String message;

这样Spring会为每个请求分别创建一个AccoutService对象,每个线程都有自己的message变量。就不会出错了。

但坏处是创建@Service bean的开销往往比較大,会导致程序性能下降。


2. 使用不可变对象(Immuable Object)封装message变量
定义例如以下类:
class MessageWrapper {
private String message; public MessageWrapper(String msg) {
this.message = msg;
} // 仅仅提供get方法
public String getMessage() {
return this.message;
}
}

AccountService的foo1()方法改动例如以下:

@Service
public class AccountService {
public MessageWrapper foo1() {
if (true) {
return new MessageWrapper("a");
} else {
return new MessageWrapper("b");
} // ... ...
}

这样便能够完美避免线程安全问题,又不会带来过多的额外开销。

Spring MVC不要在@Service bean中保存状态的更多相关文章

  1. [翻译]Spring MVC RESTFul Web Service CRUD 例子

    Spring MVC RESTFul Web Service CRUD 例子 本文主要翻译自:http://memorynotfound.com/spring-mvc-restful-web-serv ...

  2. 程序中保存状态的方式之Cookies

    程序中保存状态的方式之 Cookies,之前写过一篇关于ViewState的.现在继续总结Cookies方式的 新建的测试页面login <%@ Page Language="C#&q ...

  3. 程序中保存状态的方式之ViewState

    程序中保存状态的方式有以下几种: 1.Application 2.Cookie 3.Session 4.ViewState:ViewState是保存状态的方式之一,ViewState实际就是一个Hid ...

  4. 在C 函数中保存状态:registry、reference和upvalues

    在C函数中保存状态:registry.reference和upvalues      C函数能够通过堆栈来和Lua交换数据,但有时候C函数须要在函数体的作用域之外保存某些Lua数据.那么我们想到全局变 ...

  5. Spring MVC page render时jsp中元素相对路径的解决办法

    前段时间做了用Spring Security实现的登录和访问权限控制的功能,但是page render使用的是InternalResourceResolver,即在spring的servlet配置文件 ...

  6. spring MVC 管理HttpClient---实现在java中直接向Controller发送请求

    在spring MVC中,大多数时候是由客户端的页面通过ajax等方式向controller发送请求,但有时候需要在java代码中直接向controller发送请求,这时可以使用HttpCilent实 ...

  7. spring mvc 接收表单 bean

    spring MVC如何接收表单bean 呢? 之前项目中MVC框架一直用struts2,所以我也就按照struts2 的思维来思考 页面loginInput.jsp: <?xml versio ...

  8. spring mvc 数据校验(bean实体注解实现)

    spring mvc 数据校验 1.添加个jar (jar与一版本会冲突) <dependency> <groupId>com.fasterxml</groupId> ...

  9. 利用Spring MVC搭建REST Service

    之前写过一篇 利用JAX-RS快速开发RESTful 服务 今天来看下spring-mvc框架如何实现类似的功能: 一.pom.xml <?xml version="1.0" ...

随机推荐

  1. jquery /css3 全屏的渐变背景

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. node.js编译less文件

    大多数文章对于到底怎样编译less文件并没有一个详细的说明,清一色的grunt命令,看得也是晕晕的,所以也就有了这篇手记的存在. 步入正题 1.安装配置好sublime text3(包括各种实用插件) ...

  3. BZOJ1079: [SCOI2008]着色方案 (记忆化搜索)

    题意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很 ...

  4. SpringMVC+ajax返回JSON串

    一.引言 本文使用springMVC和ajax做的一个小小的demo,实现将JSON对象返回到页面,没有什么技术含量,纯粹是因为最近项目中引入了springMVC框架. 二.入门例子 ①. 建立工程, ...

  5. linux下nginx、php和mysql安装配置

    一.安装nginx 安装nginx yum install -y epel-release yum install nginx -y 查看nginx软件包包括了哪些文件 rpm -ql nginx 启 ...

  6. Centos下PHP7.1打开Oracle扩展

    背景 最近因为项目研究了一下PHP集成Oracle,虽然这个组合很奇葩,但万一用到请勿采坑~ 环境 CentOS Linux release 7.3.1611 (Core) PHP7.1.1 安装or ...

  7. ThinkPHP5.X PHP5.6.27-nts + Apache 通过 URL 重写来隐藏入口文件 index.php

    我们先来看看官方手册给出关于「URL 重写」的参考: 可以通过 URL 重写隐藏应用的入口文件 index.php ,Apache 的配置参考: 1.http.conf 配置文件加载 mod_rewr ...

  8. C语言学习6

    int i; 定义整形变量i int *p;  p为指向整型数据的指针变量 int a[n]: 定义整形数组a,他有n个元素 int *p[n]:   定义指针数组p,它有n个指向整型数据的指针元素组 ...

  9. 商业研究(20):滴滴出行,进军海外包车?与OTA携程和包车创业公司,共演“三国杀”?看看分析师、投资人和权威人士等10个人的观点碰撞

     小雷友情提示:创业有风险,投资需谨慎.      前一篇文章,在探讨境外游创业公司-皇包车和易途8的时候,提到"滴滴如果进军海外包车,为海外华人提供打车和包车服务,有较大可能对海外包车公司 ...

  10. swagger & api & swagger ui

    swagger & api swagger ui # run server $ swagger project start api-app # call api $ curl http://1 ...