假设我定义了以下类:
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”模式,我希望它使用与“a1”注释的A.class绑定的任何内容,以及“/ y”模式绑定到A.class并使用“a2”注释的任何内容。类似的东西:
serve("/x").with(???);
serve("/y").with(???);
应该有什么而不是'???'?有可能吗?
答案 0 :(得分:1)
这里有两个问题:一个是使用serve
方法改变XServlet的绑定注释,另一个是根据XServlet的注释改变A的绑定。
一半的服务方法很容易解决:手动创建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 */ };
}
文档: