线程安全 struts 网络应用 spring
Thread safe struts web app with spring
在 struts 2 和 spring 基于 Web 的应用程序中,请考虑以下示例。
BookManager
有一个动作,returns 一本 Map
本书给客户。它从 injected
by Spring
的服务层获取地图
public class BookManager extends ActionSupport {
//with setter and getter
private Map<String, BookVO> books;
@inject
BookService bookservice
@Action("book-form")
public String form(){
setBooks(bookservice.getAllBooks());
}
}
服务层从 DB 和 returns 地图获取图书列表。
@Named
public class BookService(){
private Map<String,BookVO> books;
public Map<String,BookVO> getAllBooks(){
books = new HashMap<String,BookVO>();
//fill books from DB
return books;
}
}
我测试过,发现上面的实现不是线程安全的。
- 我可以通过从
BookService
中删除私有字段 books
并像方法 HashMap<String,BookVO>() books = new HashMap<String,BookVO>();
一样使用它来使代码线程安全。为什么此更改使代码线程安全?
- struts 操作是线程安全的,难道这不能确保甚至非线程安全的 spring 服务以线程安全的方式运行。
- 如果我在操作中使用非线程安全版本的服务,通过创建
new
服务对象而不是使用 spring 注入,我将不会遇到任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它是线程安全的!
I can make the code thread safe by removing private field books from BookService and use it like method HashMap() books = new HashMap();. Why this change make the code thread safe ?
因为方法级变量是线程安全的,而class级变量不是。
The struts action is thread safe, shouldn't this assure that the even non thread safe spring service runs in a thread safe manner ?
没有。这取决于。
If I use the non thread safe version of service in my action, by making a new service object instead of using spring inject, I will face no issue. Why? If the service is not thread safe why making a new instance and calling it will be thread safe!
如果您在操作中手动实例化它,您将创建该操作私有的对象实例,线程安全,因为操作是线程本地的,并且由您管理(这意味着如果您的 BookService
class 中有一些 @Inject
,容器不会解析它们)。
如果您让容器管理 DI,则该实例不是线程安全的;您使用的 (@Inject
, @Named
) 不仅仅是 "Spring", 它是 Java EE, 是仅在支持 CDI 的应用程序 (JSR-299)。
CDI bean 不是线程安全的。您应该使用 EJB3's @Singleton
for this to be thread-safe,但您真的不需要在 class 级别保留该属性,因为它仅用于返回,然后留在那里以备下次覆盖。
顺便说一句,考虑使用参考 CDI(在 JBOSS 中焊接)和 ,值得一试。
在 struts 2 和 spring 基于 Web 的应用程序中,请考虑以下示例。
BookManager
有一个动作,returns 一本 Map
本书给客户。它从 injected
by Spring
public class BookManager extends ActionSupport {
//with setter and getter
private Map<String, BookVO> books;
@inject
BookService bookservice
@Action("book-form")
public String form(){
setBooks(bookservice.getAllBooks());
}
}
服务层从 DB 和 returns 地图获取图书列表。
@Named
public class BookService(){
private Map<String,BookVO> books;
public Map<String,BookVO> getAllBooks(){
books = new HashMap<String,BookVO>();
//fill books from DB
return books;
}
}
我测试过,发现上面的实现不是线程安全的。
- 我可以通过从
BookService
中删除私有字段books
并像方法HashMap<String,BookVO>() books = new HashMap<String,BookVO>();
一样使用它来使代码线程安全。为什么此更改使代码线程安全? - struts 操作是线程安全的,难道这不能确保甚至非线程安全的 spring 服务以线程安全的方式运行。
- 如果我在操作中使用非线程安全版本的服务,通过创建
new
服务对象而不是使用 spring 注入,我将不会遇到任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它是线程安全的!
I can make the code thread safe by removing private field books from BookService and use it like method HashMap() books = new HashMap();. Why this change make the code thread safe ?
因为方法级变量是线程安全的,而class级变量不是。
The struts action is thread safe, shouldn't this assure that the even non thread safe spring service runs in a thread safe manner ?
没有。这取决于。
If I use the non thread safe version of service in my action, by making a new service object instead of using spring inject, I will face no issue. Why? If the service is not thread safe why making a new instance and calling it will be thread safe!
如果您在操作中手动实例化它,您将创建该操作私有的对象实例,线程安全,因为操作是线程本地的,并且由您管理(这意味着如果您的 BookService
class 中有一些 @Inject
,容器不会解析它们)。
如果您让容器管理 DI,则该实例不是线程安全的;您使用的 (@Inject
, @Named
) 不仅仅是 "Spring", 它是 Java EE, 是仅在支持 CDI 的应用程序 (JSR-299)。
CDI bean 不是线程安全的。您应该使用 EJB3's @Singleton
for this to be thread-safe,但您真的不需要在 class 级别保留该属性,因为它仅用于返回,然后留在那里以备下次覆盖。
顺便说一句,考虑使用参考 CDI(在 JBOSS 中焊接)和