Spring bean的singleton / session范围是否要求必须同步对其所有字段的访问?通过“synchronized”关键字或使用包“java.util.concurrent”中的某些类来说。
例如,这段代码不是线程安全的吗? (复制/来自here):
@Component
@SessionScoped
public class ShoppingCart {
private List<Product> items = new ArrayList<Product>();
public List<Product> getAllItems() {
return items;
}
public void addItem(Product item) {
items.add(item);
}
}
答案 0 :(得分:24)
当您使用Spring容器中的singleton
作用域时,表明从容器中检索bean的所有线程都将使用相同的实例。因此,在这种情况下,项目的状态列表在线程之间共享和修改,您必须同步对列表的访问以保护您的应用程序免受ConcurrentModificationException
的攻击。
但是,Spring的通常做法是使用无状态对象构建应用程序,这些对象没有在应用程序的整个生命周期中都会发生变化的状态。
对于session
范围,您可能不太可能看到并发问题,因为bean只能由当前登录的用户访问。但是,有可能(至少在网络上)在同一个会话中有多个请求,在这种情况下,您需要采取相同的预防措施,就像bean是单例一样。
同样,保护自己的最佳方法是尽量保持豆子无国籍。如果你有一个需要状态的bean,你应该考虑使用prototype
范围,每次从容器中检索一个新的bean实例。
答案 1 :(得分:0)
只有该会话的用户才能访问此类,但ArrayList不是线程安全的,如本讨论中所示:http://forums.sun.com/thread.jspa?threadID=5355402
您需要确保您的类完全是线程安全的,因为SessionScoped将确保它仅由每个会话使用,因此一个会话无法访问它。
您可能需要查看此讨论中的评论以获取更多信息: http://wheelersoftware.com/articles/spring-session-scoped-beans.html
答案 2 :(得分:-4)
基本上,对于发起会话的每个用户,将为该用户创建新的ShoppingCart
并确定该会话的范围。
您的课程是线程安全的。初始化
private List<Product> items = new ArrayList<Product>();
是一个线程安全的初始化和
addItem(Product item)
是一个原子操作,因此也是线程安全的。