2

次のクラスが定義されているとします。

public interface A {}

public class A1 implements A {}

public class A2 implements A {}

public class XServlet<T extends A> extends HttpServlet {
    public XServlet(T delegate){}
}

さらに、Guice モジュールの 1 つに、愚かなバインディングがあります。

bind(A.class).annotatedWith(Names.named("a1")).to(A1.class);
bind(A.class).annotatedWith(Names.named("a2")).to(A2.class);

ここで、「XServlet」の 2 つのインスタンスを異なる引数で定義する ServletModule を作成する必要があります。「/x」パターンでは、「a1」で注釈が付けられた A.class にバインドされているものを使用し、「/y」パターンでは、A.class にバインドされ、「a2」で注釈が付けられているものを使用します。何かのようなもの:

serve("/x").with(???);
serve("/y").with(???);

「???」の代わりに何が必要ですか? それはまったく可能ですか?

4

1 に答える 1

1

ここで 2 つの問題があります。1 つは XServlet のバインディング アノテーションをserveメソッドで変更することであり、もう 1 つは XServlet のアノテーションに基づいて A のバインディングを変更することです。

serve メソッドの半分は、解決するのが非常に簡単です。手動でKey. これにより、「/x」が にバインドされ@Named("a1") XServletます。

serve("/x").with(Key.get(XServlet.class, Names.named("a1")));

後半は「ロボットの脚の問題」として知られており、プライベート モジュールを使用して修正できます。

install(new PrivateModule() {
  @Override void configure() {
    // These are only bound within this module, and are not visible outside.
    bind(A.class).to(A1.class);
    bind(XServlet.class).annotatedWith(Names.named("a1"));
    // But you can expose bindings as you'd like.
    expose(XServlet.class).annotatedWith(Names.named("a1"));
  }
});

更新:前に言及した名前付きバインディングをプライベート モジュールに移動できない場合は、プライベート モジュールの注釈なしバインディングを別のモジュールの注釈付きバインディングにいつでもバインドできます。プライベート モジュールのバインディングは次のようになります。

// Fulfill requests for an unannotated A by looking up @Named("a1") A,
// though @Named("a1") A is bound elsewhere.
bind(A.class).to(Key.get(A.class, Names.named("a1")));

これらの数十をバインドしようとしている場合は、次のようなプライベートな静的関数を作成する方が簡単な場合があります。

private static Module moduleForServlet(
    final Class<? extends A> aClass, final String namedAnnotationString) {
  return new PrivateModule() { /* see above */ };
}

ドキュメント:

于 2012-12-23T03:29:12.897 に答える