@ApplicationScoped JSF 托管 bean 的并发性

Posted

技术标签:

【中文标题】@ApplicationScoped JSF 托管 bean 的并发性【英文标题】:Concurrency of @ApplicationScoped JSF managed beans 【发布时间】:2016-05-02 18:48:54 【问题描述】:

我正在使用 Mojarra 2.2.12,在我们的项目中,我们有一些 @ApplicationScoped bean。例如:

@ManagedBean
@ApplicationScoped
public class AppScopedBean

    private int commonValueForClients;

    //GET, SET

    public void evalNew()
        int newCommonVal;
        //Evaluation of the new value, doesn't depend on the commonValueForClients
        commonValueForClients = newCommonVal;
    

我的问题是我们应该担心新分配值的可见性吗?

我在the spec 中找不到JSF 基础结构必须同步对@ApplicationScoped bean 字段的访问。那么,特别是对于 Mojarra 2.2.12,我们应该将该字段声明为 volatile 还是显式同步对它的访问?

【问题讨论】:

在我看来,您选择了错误的 bean 范围。无法选择特定托管 bean 的正确范围将导致严重的痛苦和痛苦。 @Tiny 也许,我认为缓存严格来说并不适合托管 bean。这更像是一种服务目的。 【参考方案1】:

JSF在任何范围内同步对托管 bean 的任何访问。

这是你的责任。将现有的并发/同步包装器用作字段类型,例如AtomicIntegerConcurrentHashMapCollections#synchronizedList() 等。如果不存在此类包装器,则仅将volatile 用作最后的手段。

在应用程序范围的 bean 中,可变对象的同步是绝对必要的。在例如的情况下HashMap,否则您甚至可能冒着stuck thread(100% CPU)的风险。在会话范围的 bean 中没有那么严格的必要性,因为它们只会在最终用户在同一个会话上打开多个 HTTP 连接时被同时访问,并且 by default 仅在产生两个物理上不同的浏览器实例时才会发生,但它们会反过来默认情况下已经不共享会话。所以它只会在机器人/黑客的情况下发生,因此仍然强烈建议在会话范围的 bean 中也处理这个问题。在视图范围的 bean 中几乎没有必要,因为 ajax 请求在 by specification 排队,但在 PrimeFaces 中它可以被 <p:ajax async="true"> 关闭,您还必须在视图范围的 bean 中考虑到这一点。在请求范围的 bean 中完全没有必要。

如果您碰巧手头有 CDI,您还可以选择使用自定义注释和 CDI 拦截器来模仿 EJB 的 @Lock 注释。这在 Stephan Kintelius 的博客中有详细说明:Concurrency control for CDI,恰好在您提问的前一天发布。请记住,JSF bean 管理工具根据 JSF 2.3 已弃用,而支持 CDI。另请参阅Backing beans (@ManagedBean) or CDI Beans (@Named)? 如果可以,请移至 CDI 进行 bean 管理。

【讨论】:

有趣,但规范并不太清楚。实现是否可以同步它......?我的意思是,为了避免过度同步并使用一些特定于 impl 的功能来提高性能。 如果不存在这样的包装器,则仅将 volatile 用作最后的手段。 你为什么这么认为?我认为 volatile 字段与不可变对象相结合是线程安全的标准技术。 实现确实可以选择这样做,但这显然是低效的,因为并不总是需要同步。必要性取决于 bean 类的设计,这从实现中是不可见的。至于volatile,这些包装器不是不可变的。 我想再问你一个关于SessionScoped beans 的问题。我想,同步对他们来说是一件可取的事情。容器可以在持久化会话以及 Web 应用程序时访问此类 bean 以响应请求。这样,即使没有从相同的浏览器/机器人/黑客访问,也可能发生并发访问。这不是真的吗? 这可能是必要的,但不那么严格,因为这些条件取决于 Web 应用程序设计和受众。至于会话持久性,在那一刻首先没有请求处理它,容器已经担心这部分。对于同一会话上的请求,容器会同步同一 HTTP 连接上的请求(另请参阅“默认情况下”链接)。

以上是关于@ApplicationScoped JSF 托管 bean 的并发性的主要内容,如果未能解决你的问题,请参考以下文章

将 JSF 托管 bean 迁移到 CDI 托管 bean

CDI 托管 bean 和 JSF 托管 bean 可以相互通信吗?

Spring JSF 集成:如何在 JSF 托管 bean 中注入 Spring 组件/服务?

JSF-2.3 找不到我的 @Named CDI-1.2 托管 bean

在页面加载时调用 JSF 托管 bean 操作

如何以编程方式注册 JSF 托管 bean?