次の目的を達成するための決定的なアプローチを見つけるのに苦労しています。
クライアントからのリクエストスコープの操作呼び出しの優れた実装があります。これらの操作は高速で軽快、つまり 10 ミリ秒未満であることが期待されており、重い処理は別のスレッドまたはスレッド プールで呼び出された操作とは無関係に非同期で実行される必要があります。
これらのスレッドを実行している間、リクエストスコープの変数をスレッドに注入する必要があります。これらのスレッドが実行されると、リクエストは完了して実行されるため、つまりスレッドの実行はリクエスト スコープ外であるため、リクエスト スコープの変数を直接注入することはできません。
1つの解決策はServletScopes.scopeRequestメソッドのようです。それを効果的に使用するために、すべてのリクエスト スコープ オブジェクト参照を効果的にマップにコピーし、継続中にそれらをシードするクラス RequestScopePropagator を作成しました。
これが正しいアプローチであるかどうかは確信が持てません。より適切な方法/アプローチはありますか?
import com.google.inject.Binding;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletScopes;
import com.google.inject.spi.BindingScopingVisitor;
public class RequestScopePropagator {
private final Map<Key<?>, Provider<?>> requestScopedValues = new HashMap<>
();
Logger logger =
Logger.getLogger(this.getClass().getName());
@Inject
RequestScopePropagator(Injector injector) {
for (Map.Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
Key<?> key = entry.getKey();
Binding<?> binding = entry.getValue();
if (binding.acceptScopingVisitor(IS_REQUEST_SCOPED)) {
requestScopedValues.put(key, binding.getProvider());
}
}
}
private final BindingScopingVisitor<Boolean> IS_REQUEST_SCOPED = new BindingScopingVisitor<Boolean>() {
@Override
public Boolean visitScopeAnnotation( Class<? extends Annotation> scopeAnnotation) { return scopeAnnotation == RequestScoped.class; }
@Override
public Boolean visitScope(Scope scope) {
return scope == ServletScopes.REQUEST; }
@Override
public Boolean visitNoScoping() {
return false; }
@Override
public Boolean visitEagerSingleton() {
return false; }
};
public <T> Callable<T> continueRequest(Callable<T> callable) {
Map<Key<?>, Object> seedMap = new HashMap<Key<?>, Object>();
try {
for (Map.Entry<Key<?>, Provider<?>> entry : requestScopedValues.entrySet()) {
if (!entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(HttpServletRequest.class)
&& !entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(HttpServletResponse.class)
&& !entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(Map.class))
seedMap.put(entry.getKey(), entry.getValue().get());
}
} catch (Exception e) {
logger.log(Level.SEVERE, "could not add request cope values in seed map for continuing request scope", e);
throw new AltAppOpsException("could not add request cope values in seed map for continuing request scope");
}
return ServletScopes.scopeRequest(callable, seedMap);
}
}