Guice:基于另一个绑定值绑定

时间:2014-06-13 22:12:45

标签: java guice

假设我有一个班级Environment,其中包含子类ServiceAServiceB
同样在我的模块中:

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)

1 个答案:

答案 0 :(得分:0)

为什么要直接注射ServiceAServiceB?您现在知道它根据您的配置不安全。

如果您define your own binding annotations,您似乎只需依靠@Production Environment@Test Environment。理想情况下,您应该对其进行设置,以便没有编译配置将在运行时进行barf ,除非它对于祝福服务名称&#34;而言至关重要。住在Guice中,你可以将它重构为switch语句,避免各种运行时消化不良。

通过限制ServiceAServiceB的可见性,您可以无法直接注入实现,并且可以轻松而明显地注入具体实现,无论它们是否受到祝福。您还可以使用requireExplicitBindings来帮助您保持代码对于仅注入接口的诚实。