在struts 2和基于弹簧网的应用程序中,请考虑以下示例。
struct
有一项操作可将BookManager
本书退回给客户。它从服务层获取地图,即Spring {/ p>为Map
injected
服务层从DB获取图书列表并返回MAP。
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());
}
}
我测试过并发现上述实现不是线程安全的。
@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;
}
}
删除私有字段books
来使代码线程安全,并像方法BookService
一样使用它。为什么这个改变使代码线程安全?HashMap<String,BookVO>() books = new HashMap<String,BookVO>();
服务对象而不是使用spring inject,我将面临任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它将是线程安全的!答案 0 :(得分:1)
我可以通过从BookService中删除私有字段书来使代码线程安全,并像方法HashMap()books = new HashMap();一样使用它。为什么这个改变使代码线程安全?
因为方法级变量是线程安全的,而类级变量不是。
struts动作是线程安全的,这不应该确保甚至非线程安全弹簧服务以线程安全的方式运行吗?
不。这取决于。
如果我在我的操作中使用非线程安全版本的服务,通过创建一个新的服务对象而不是使用spring注入,我将面临任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它将是线程安全的!
如果您在操作中手动实例化它,那么您正在创建该操作的私有实例,由于操作是ThreadLocal,因此是线程安全的,并由您管理(这意味着您的BookService
类具有其中有一些@Inject
,容器无法解析它们。)
如果您拥有由容器管理的DI,则该实例不是线程安全的;您正在使用的内容(@Inject
,@Named
)不仅仅是“Spring”,它是Java EE,它是JSR-330(依赖注入)的实现,仅在支持CDI的应用程序中可用(JSR) -299)。
CDI bean不是线程安全的。您应该使用EJB3's @Singleton
for this to be thread-safe,但实际上您不需要在类级别保留该属性,因为它仅用于返回,然后在下次时被覆盖。