【问题标题】:Thread safe struts web app with spring带弹簧的线程安全的Struts Web应用程序
【发布时间】:2016-02-08 16:26:51
【问题描述】:

在基于 struts 2 和 spring web 的应用程序中,请考虑以下示例。

BookManager 有一个动作,它向客户端返回书籍的Map。它从 Spring 的injected 服务层获取地图

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 中获取图书列表并返回一个 MAP。

@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&lt;String,BookVO&gt;() books = new HashMap&lt;String,BookVO&gt;(); 一样使用它。为什么此更改使代码线程安全?
  2. struts 动作是线程安全的,这不应该确保即使是非线程安全的 spring 服务也以线程安全的方式运行。
  3. 如果我在操作中使用非线程安全版本的服务,通过创建new 服务对象而不是使用弹簧注入,我将不会遇到任何问题。为什么?如果服务不是线程安全的,为什么要创建一个新实例并调用它是线程安全的!

【问题讨论】:

  • 如果操作不是线程安全的,则不会。

标签: java spring multithreading struts2 cdi


【解决方案1】:

我可以通过从 BookService 中删除私有字段书籍来使代码线程安全,并像方法 HashMap() books = new HashMap(); 一样使用它。为什么此更改使代码线程安全?

因为方法级变量是线程安全的,而类级变量不是。

struts 动作是线程安全的,难道这不应该保证即使是非线程安全的 spring 服务以线程安全的方式运行吗?

不。视情况而定。

如果我在操作中使用非线程安全版本的服务,通过创建一个新的服务对象而不是使用 spring 注入,我将不会遇到任何问题。为什么?如果服务不是线程安全的,为什么要创建一个新实例并调用它是线程安全的!

如果您在操作中手动实例化它,您将创建该操作私有的该对象的实例,线程安全,因为操作是 ThreadLocal,并由您管理(这意味着如果您的 BookService 类有一些 @ 987654324@,容器不会解析)。

如果您让容器管理 DI,则实例不是线程安全的;您正在使用的(@Inject@Named)不仅仅是“Spring”,它是 Java EE,是仅在启用 CDI 的应用程序 (JSR-299) 中可用的 JSR-330(依赖注入)的实现。
CDI bean 不是线程安全的。您应该使用EJB3's @Singleton for this to be thread-safe,但您确实不需要在类级别保留该属性,因为它仅用于返回,然后留在那里以供下次覆盖。

顺便说一句,考虑使用带有Struts2 CDI-plugin 的参考 CDI(JBOSS 中的焊接),值得一试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 2013-01-25
    • 2014-09-19
    • 1970-01-01
    • 2019-02-12
    • 2015-07-02
    相关资源
    最近更新 更多