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 模块中,我有一些愚蠢的绑定:

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

现在我需要创建一个 ServletModule,它定义了两个具有不同参数的“XServlet”实例。对于“/x”模式,我希望它使用绑定到 A.class 并使用“a1”注释的任何内容,对于“/y”模式,我希望它使用绑定到 A.class 并使用“a2”注释的任何内容。就像是:

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

应该有什么而不​​是'???'?有可能吗?

4

1 回答 1

1

这里有两个问题:一个是用serve方法改变XServlet的绑定注解,另一个是根据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 回答