应用程序范围ManagedBean方法的可伸缩性和线程安全性

时间:2011-05-04 22:26:07

标签: jsf

在测试期间,我们的应用程序构建f:selectItems列表的方式暴露了一个弱点,具体而言,在我们的某些实体上输入真正长名称,通过进行非常广泛的选择来固定页面对齐。

其中许多selectItem列表在多个视图和支持bean中都是重复的,所以我想整合它们的创建。

我们已经有了一个应用程序作用域bean,它提供了List< SelectItem>对于枚举,我最初的想法是将它们放在那里。

但是,我有一些问题。我们正在使用jsf 1.2(如果重要的话)

1)我的理解是应用程序作用域bean是单例,因为单个实例被实例化并放置在会话上下文中。它们不像EJB3单例,只有一个线程可以访问任何方法,因此多个请求不会阻止尝试访问不同的方法。这是对的吗?

2)我怀疑每个方法都必须同步,以防止多个线程调用相同的方法互相破坏。即使在该方法中访问的唯一类成员是线程安全的无状态@EJB?

,情况就是这样

以下是其中一个将在20个视图中使用的实现。其他10个实体的实现类似。此外,还注册了相应的转换器。

public synchronized List<SelectItem> getAccountSelect(){
    List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
    Collections.sort(list, new AccountByActiveByName());
    List<SelectItem> result=new ArrayList<SelectItem>(list.size());
    for(Account row : list){
        result.add(new SelectItem(row, 
                StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
    }
    return result;
}

任何建议表示赞赏

2 个答案:

答案 0 :(得分:2)

如果在getter中而不是在构造函数/ postconstruct中进行数据加载是非常必要的,那么绝对没有必要将它作为应用程序作用域bean。只需将其作为请求作用域,在构造函数/ postconstruct中执行数据加载作业。

答案 1 :(得分:2)

在我工作的jsf应用程序中,我们在Application范围bean中加载了几乎所有的引用数据(主要是selectOneMenues的值),并在这些bean的构造函数中设置了值。然后,数据可通过getter用于其他托管bean和视图,但是全局化并集中用于应用程序。由于这些值仅通过getter读取,因此无需同步。

然后我们通过jmx使用重载方法将bean作为mbeans公开,以便可以根据需要更新它们。重新加载方法是同步的,以便在短暂的重新加载期间阻塞。

在上面的示例中,您似乎只能返回selectItems的集合,因此只要事先设置了值,您就可以使用此方法并且仍可以正常提供多个线程:

public List<SelectItem> getAccountSelectItems() {
    return this.accountSelectItems;
}

只需将此私有成员添加到您的bean:

private List<SelectItem> accountSelectItems;

并在构造函数中设置它:

public AccountBean() {
    List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
    Collections.sort(list, new AccountByActiveByName());
    this.accountSelectItems = new ArrayList<SelectItem>(list.size());

    for(Account row : list) {
        this.accountSelectItems.add(new SelectItem(row, StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
    }
}

另一方面,如果数据不断变化且需要更新,您可能最好只为每个会话或每个请求加载它,尽管您可以使用Quartz或其他一些计时器在应用程序范围内定期重新加载它如果实时不是应用中此数据的基本要求,请保持数据从数据源中读取。如果您正在重新加载数据,那么如果您正在使用应用程序范围,则需要同步这些操作。