Использование методов провайдера или @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
Этот метод хорош, но, вероятно, полезен только тогда, когда у вас есть контроль над экземпляром Injector, и только когда модуль требует сложных зависимостей. Тем не менее, я нашел реальную потребность в этом в реальном проекте на работе. Если бы я это сделал, то мог бы и кто-то другой.