1

CDI管理のJSFBean(RequestScoped)にクラスを注入することと、それらの注入されたクラスがRequestScope中にスレッドセーフであるかどうかについて質問があります。

たぶん、最初にサンプルコードを示すのが最善でしょう:

----------------- JSF Bean、CDIを使用------------------

import javax.enterprise.context.RequestScoped;
...

@Named
@RequestScoped
public class DemoBean {

    @Inject
    LocalService localService;

    @PostConstruct
    public void init() {
        localService.reloadCache();
    }

    public String getName() {
        return localService.getName();
    }

    public String getAge() {
        return localService.getAge();
    }

}

-----------------サービス、CDIを使用------------------

@Named
public class LocalService {

    private String name;
    private String age;

    public void reloadCache() {
        name = null;
        age = null;
        name = // slow SQL on remote Service, that needs to be cached
        age = // slow SQL on remote Service, that needs to be cached
    }

    public String getName() {
        // do some work, e.g. logging
        return name;
    }

    public String getAge() {
        // do some work, e.g. logging
        return age;
    }
}

JSF Beanの「DemoBean」は「LocalService」クラスを使用してDBからデータを取得します(リモートEJBを介して、ただしここでは重要ではありません)。「LocalService」クラスで、次の2つの理由から、リクエスト中にSQL結果をキャッシュしたいと思います。

  • SQLクエリのパフォーマンスが低い(多くの結合、多くのデータなど)
  • JSFライフサイクル:6つのJSFライフサイクルのすべてでSQLクエリを実行したくありません

注入された「LocalService」クラスは、多くのJSF Bean(JSFページへの多数の同時呼び出し)が同時に使用する場合、どのように動作しますか?挿入された「LocalService」インスタンスは他のスレッドと共有されているため、スレッドセーフではありませんか?

この場合、サービススレッドを安全にするにはどうすればよいですか?

例(LocalService内)

Thread1: call reloadCache()
Thread1: call getName()

Thread1 is interrupted in the middle of getName() by Thread2

Thread2: call reloadCache()

Thread2 is interrupted in the middle of reloadCache() -> name is null

Thread1: continue execution of getName() and return name -> which is null at this moment -> very bad

この例は私のコードの非常に単純化されたバージョンですが、それが私の質問を理解できるようにしたことを願っています

ありがとう、クリスチャン

4

1 に答える 1

3

スコープが明示的に宣言されていないCDIBeanのデフォルトのスコープはです@Dependent。このアノテーションのjavadocを調べると、特定のケースでは、の各インスタンスがDemoBean独自ののインスタンスを持つことが保証されていることがわかりますLocalService

コンテナによって作成されているオブジェクトに注入されたBeanのインスタンスはすべて、新しく作成されたオブジェクトのライフサイクルにバインドされます。

新しく作成されたインスタンスごとに作成さDemoBeanれ、同時に破棄されるので、これを読みました(これは長期的には費用がかかる可能性があります)

あなたの質問とは無関係です:非正規化。データに到達するためにホップが多すぎることに気付いた場合、それは過度の結合とそれに関連するパフォーマンスコストの問題に対する単純で直接的な答えです。しかし、あなたはおそらくすでにこれを知っています。

于 2013-01-30T15:55:26.263 に答える