假设我有一个班级Environment
,其中包含子类ServiceA
和ServiceB
。
同样在我的模块中:
bind(ServiceA.class).annotatedWith(Names.named("Production Service A")).to(...)
bind(ServiceA.class).annotatedWith(Names.named("Test Service A")).to(...)
bind(ServiceB.class).annotatedWith(Names.named("Production Service B")).to(...)
bind(ServiceB.class).annotatedWith(Names.named("Test Service B")).to(...)
在其他地方,我有类似的内容:
bindConstant().annotatedWith(Names.named("Blessed Service Name")).to(...)
我想要做的是,基于"Blessed Service Name"
绑定的值(可以采用上面任何第一组绑定的名称),绑定Environment
注释{ {1}}到相应的绑定项。也就是说,如果Names.named("Blessed Service")
绑定到值"Blessed Service Name"
,那么这里的两个:
"Production Service A"
会是一样的。如果上面的@Inject @Named("Blessed Service") Environment blessedService;
@Inject @Named("Production Service A") ServiceA productionA;
是blessedService
而不是ServiceA
,那么如果注入工作(在合理范围内),我也会喜欢它。
我听说Environment
可以完成我想要的大部分内容,就像它一样,
我可以这样做:
MapBinder
但我能做些什么呢
public class BlessedServiceModule extends AbstractModule {
@Override
protected void configure() {
requireBinding(Key.get(String.class, Names.named("Blessed Service Name"));
requireBinding(Key.get(new TypeLiteral<Map<String, Provider<Environment>>>(){}, Names.named("All Services"));
}
@Provides @Named("Blessed Service")
public Provider<Environment> getBlessedEnvironment(@Named("Blessed Service Name") String serviceName, @Named("All Services") Map<String, Provider<Environment>> environments) {
return environments.get(serviceName);
}
}
在适当的情况下工作? (即如果它被祝福则正常注入@Inject @Named("Blessed Service") ServiceA blessedService;
,如果"Production Service A"
被祝福则注入barfs)
答案 0 :(得分:0)
为什么要直接注射ServiceA
或ServiceB
?您现在知道它根据您的配置不安全。
如果您define your own binding annotations,您似乎只需依靠@Production Environment
和@Test Environment
。理想情况下,您应该对其进行设置,以便没有编译配置将在运行时进行barf ,除非它对于祝福服务名称&#34;而言至关重要。住在Guice中,你可以将它重构为switch语句,避免各种运行时消化不良。
通过限制ServiceA
和ServiceB
的可见性,您可以无法直接注入实现,并且可以轻松而明显地注入具体实现,无论它们是否受到祝福。您还可以使用requireExplicitBindings来帮助您保持代码对于仅注入接口的诚实。