RequestScope ( https://code.google.com/p/google-guice/wiki/ServletModule#Using_RequestScope ) を使用するための Guice wiki ドキュメントに従って問題が発生しています。
リクエスト スコープの ExecutorService があるアプリケーションをセットアップしようとしています。私の使用例は、ドキュメントの例からパターン化されています。完全を期すために、他の関連クラスを含めようとしました。
主な違いは、リクエスト パラメーターからリテラル値を取得するのではなく、フィルター内で ExecutorService のインスタンスをインスタンス化していることです。
@Singleton
public class ExecutorServiceScopingFilter implements Filter {
public ExecutorService getExecutor() {
return Executors.newFixedThreadPool(10, ThreadManager.currentRequestThreadFactory());
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
ExecutorService executor = getExecutor();
HttpServletRequest httpRequest = (HttpServletRequest) req;
httpRequest.setAttribute(Key.get(ExecutorService.class).toString(), executor);
chain.doFilter(req, resp);
}
...
}
私のサーブレット モジュールでは、フィルターをバインドします。
public class MyServletModule extends ServletModule {
@Override
protected void configureServlets() {
filter("/*").through(ExecutorServiceScopingFilter.class);
...
}
}
そして、モジュールを通常どおりサーブレット コンテキスト リスナーにインストールします (guice フィルターと以下のリスナーを使用するように web.xml をセットアップしました)。
public class MyServletContextListener extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
Injector injector = Guice.createInjector(
Stage.PRODUCTION,
new MyServletModule(),
new MyExampleModule(),
...
);
}
}
スコープのない POJO でプロバイダーを宣言します。
class MyExampleImpl implements IMyExample
{
@Inject
protected Provider<ExecutorService> executorProvider;
...
}
モジュールにバインドします(上記のリスナーの createInjector 呼び出しのパラメーターです):
public class MyExampleModule extends AbstractModule {
@Override
protected void configure() {
bind(IMyExample.class).to(MyExampleImpl.class);
}
}
Web アプリを起動すると、次の例外が発生します。
com.google.inject.CreationException: Guice 作成エラー:
1) java.util.concurrent.ExecutorService の実装がバインドされていませんでした。com.example.MyExampleImpl.executorProvider(MyExampleImpl.java:12) のフィールドの com.google.inject.Provider を com.example.ExampleModule.configure(ExampleModule.java:23) で検索している間
1 エラー
偽のバインディングの使用を示す関連する質問を見つけました ( Guice: Cannot inject annotated type in Request scope )。与えられた例は次のとおりです。
bind(String.class)
.annotatedWith(Names.named("name"))
.toProvider(Providers.<String>of(null));
ExecutorService をバインドするためにこれを試し、プロバイダーの null を取得しました (したがって、インジェクターは、フィルターによって定義されたバインディングを使用する代わりに、宣言されたバインディングを返します)。偽のバインディングの使用は、公式ドキュメントではまったく言及されていません。
この問題を解決し、Guice の動作についてもう少し理解するためのいくつかの質問があります。
属性を設定する以外に明示的なバインドが必要ですか (Guice のドキュメントとは異なります)?
その場合、@RequestScope アノテーションを使用して何かをバインドする必要がありますか?
Provider を実装するプロバイダーを作成する必要がありますか?
@Inject Injector オブジェクトを調べると、バインディング マップに ExecutorService のリクエスト スコープのバインディングが表示されません。このバインディングを見る必要がありますか?
実行時に ServletScope クラスの requestScopeContext スレッド ローカル変数を調べると、ExecutorService バインディングが表示されます。これは、バインディングが機能していることを示しているため、アクセスするために何かを行っていない (または間違っていることをしている) ことはありません。