У меня есть такой класс, который я создаю где-то в своем коде:
class StarryEyes {
@Inject MyValidator validator;
public StarryEyes(String name) {
//..
}
public doSomething() {
// validator is NULL
}
}
Я хочу, чтобы Guice внедрил экземпляр валидатора, который имеет аннотацию @Singleton. У меня есть модуль, который загружается при запуске, и он содержит строку:
bind(MyValidator.class);
Однако, он, кажется, не работает, так как «валидатор» всегда равен нулю. Я пробовал несколько вариантов, например:
bind(MyValidator.class)toInstance(new MyValidator());
или другие подобные вещи. Разве это не то, как должен работать Guice?
Обычно Guice нужно создавать объекты для их внедрения. Если вы просто вызовете new StarryEyes (name)
, Guice никогда не увидит этот объект, поэтому не сможет его внедрить. Вы можете вызвать injector.injectMembers (obj)
для объекта после того, как вы его создали. Я бы не рекомендовал это, так как вам следует избегать ссылки на инжектор в своем коде.
Что вам действительно нужно, так это Assisted Inject .С помощью Assisted Inject вы бы объявили конструктор для своего класса примерно так:
@Inject public StarryEyes(MyValidator validator, @Assisted String name)
Это означает, что валидатор
- это параметр, который Guice должен ввести, а name
должен быть «с помощью» (то есть предоставляется во время создания экземпляра).
Затем вы создаете такой интерфейс:
public interface StarryEyesFactory {
StarryEyes create(String name);
}
С помощью Assisted Inject Guice может реализовать эту фабрику за вас. Вы привязываете его следующим образом:
bind(StarryEyesFactory.class).toProvider(
FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class));
Затем вы вводите StarryEyesFactory
везде, где хотите создать его экземпляр. Если раньше вы вызывали new StarryEyes (name)
, то теперь вместо этого вы вызываете starryEyesFactory.create (name)
. Когда вы вызываете create (name)
на фабрике, он принимает имя, передает его конструктору и предоставляет сам привязанный валидатор.
Начиная с Guice 3 , вы делаете это с помощью FactoryModuleBuilder :
install(new FactoryModuleBuilder().build(StarryEyesFactory.class));