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
この例は私のコードの非常に単純化されたバージョンですが、それが私の質問を理解できるようにしたことを願っています
ありがとう、クリスチャン