如果需要依赖项来手动构造对象,则使用提供程序或@Provides方法非常有用。但是,如果您需要一些东西来帮助您决定如何配置绑定本身,该怎么办?事实证明,您可以使用Guice来创建(和配置)您的模块。
这是一个(人为的)例子。首先,我们要配置的模块:
/**
* Creates a binding for a Set<String> which represents the food in a pantry.
*/
public class PantryModule extends AbstractModule {
private final boolean addCheese;
@Inject
public ConditionalModule(@Named("addCheese") boolean addCheese) {
this.addCheese = addCheese;
}
@Override
protected void configure() {
Multibinder<String> pantryBinder = Multibinder
.newSetBinder(binder(), String.class);
pantryBinder.addBinding().toInstance("milk");
if (addCheese) {
pantryBinder.addBinding().toInstance("cheese");
}
pantryBinder.addBinding().toInstance("bread");
}
}
PantryModule 期望注入一个布尔值,以决定它是否应该在食品储藏室中包含奶酪。
接下来,我们将使用 Guice 来配置模块:
// Here we use an anonymous class as the "configuring" module. In real life, you would
// probably use a standalone module.
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
// No cheese please!
bindConstant().annotatedWith(Names.named("addCheese")).to(false);
bind(PantryModule.class);
}
});
Module configuredConditionalModule = injector.getInstance(PantryModule.class);
现在我们有一个配置的模块,我们将更新我们的注入器以使用它...
//...continued from last snippet...
injector = injector.createChildInjector(configuredConditionalModule);
最后,我们将得到代表我们的食品储藏室的字符串集:
//...continued from last snippet...
Set<String> pantry = injector.getInstance(new Key<Set<String>>() {});
for (String food : pantry) {
System.out.println(food);
}
如果将所有部分放在一个 main 方法中并运行它,则将获得以下输出:
milk
bread
如果将绑定更改为“addCheese”布尔值更改为 true,您将获得:
milk
cheese
bread
这种技术很酷,但可能只有在您控制注入器实例并且仅当模块需要复杂的依赖项时才有用。无休止,我发现在工作中的一个真实项目中确实需要它。如果我这样做了,那么其他人也可能这样做。