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

У меня есть класс, похожий на то, что я создаю себе где-то в своем коде:

class StarryEyes {
   @Inject MyValidator validator;

   public StarryEyes(String name) {
      //..
   }

   public doSomething() {
      // validator is NULL
   }
}

Я хочу, чтобы Guice вводил экземпляр validator, который имеет аннотацию @Singleton. У меня есть модуль, который загружается при запуске и содержит строку:

bind(MyValidator.class);

Однако, похоже, он не работает, поскольку "валидатор" всегда равен нулю. Я пробовал несколько вариантов, таких как:

bind(MyValidator.class)toInstance(new MyValidator());

или другие подобные вещи. Разве это не так, как должен работать Guice?

Ответ 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 может реализовать этот factory для вас. Вы связываете его следующим образом:

bind(StarryEyesFactory.class).toProvider(
    FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class));

Затем вы вставляете StarryEyesFactory в любом месте, где хотите создать экземпляр. Если раньше вы бы назвали new StarryEyes(name), теперь вы вызываете starryEyesFactory.create(name). Когда вы вызываете create(name) в factory, он берет имя и передает его конструктору и предоставляет сам механизм проверки.

Начиная с Guice 3, вы делаете это с помощью FactoryModuleBuilder:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));