Поле Guice Inject в классе, созданном не Guice

У меня есть такой класс, который я создаю где-то в своем коде:

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?


person Verhogen    schedule 04.08.2010    source источник


Ответы (1)


Обычно Guice необходимо создавать объекты для их внедрения. Если вы просто вызовете new StarryEyes(name), Guice никогда не увидит этот объект и не сможет внедрить его. Одна вещь, которую вы можете сделать, это вызвать injector.injectMembers(obj) для объекта после того, как вы его создали. Однако я бы не рекомендовал этого делать, поскольку вам следует избегать ссылок на инжектор в коде.

Что вам действительно нужно, так это Assisted Inject. С Assisted Inject вы должны объявить конструктор для своего класса примерно так:

@Inject public StarryEyes(MyValidator validator, @Assisted String name)

Это означает, что validator — это параметр, который должен вводить 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));
person ColinD    schedule 04.08.2010