线程安全 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;
  }

}

我测试过,发现上面的实现不是线程安全的

  1. 我可以通过从 BookService 中删除私有字段 books 并像方法 HashMap<String,BookVO>() books = new HashMap<String,BookVO>(); 一样使用它来使代码线程安全。为什么此更改使代码线程安全?
  2. struts 操作是线程安全的,难道这不能确保甚至非线程安全的 spring 服务以线程安全的方式运行。
  3. 如果我在操作中使用非线程安全版本的服务,通过创建 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 中焊接)和 ,值得一试。