Guice: вспомогательные инъекции и поставщики

Предположим, у меня есть класс следующим образом:

public class ComplicatedImpl implements Complicated {
    @Inject
    public ComplicatedImpl(Integer normal, @Assisted String assisted);

    public void addListener(Listener listener);
}

Теперь у меня есть ComplicatedFactory вот так:

public interface ComplicatedFactory {
    public Complicated build(String assisted);
}

Можно ли при использовании FactoryModuleBuilderсвязать ComplicatedFactory такой, что когда build() вызывается, мы делаем эквивалент

ComplicatedImpl impl = new ComplicatedImpl(normal, assisted);
impl.addListener(listener);
return impl;

в отличие от обычного случая возвращения нового ComplicatedImpl напрямую?

Я пытался связать ComplicatedImpl в какой-то форме Provider, но кажется, что я буду ходить по кругу с этим...

1 ответ

Я не верю, что это возможно в Guice; FactoryModuleBuilder может делать очень мало, кроме как смешивать явные аргументы конструктора с зависимостями. К счастью, написание ручной фабрики относительно просто:

public class ListeningComplicatedFactory {
  @Inject Provider<Integer> normalProvider;

  public Complicated createComplicated(String assisted, Listener listener) {
    ComplicatedImpl impl = new ComplicatedImpl(normalProvider.get(), assisted);

    // If ComplicatedImpl uses member injection, inject an Injector and call
    // injector.injectMembers(impl) to call @Inject-annotated methods/fields.

    impl.addListener(listener);
    return impl;
  }
}

Если вы готовы поставить addListener на Complicated Интерфейс, у вас также есть возможность написать оболочку, которая внедряет ComplicatedFactory, создает новые экземпляры и вызывает addListener на них сразу. Это может быть особенно эффективно, если вы связываете ComplicatedFactory в PrivateModule, а затем открываете только свой новый ComplicatedWrapperFactory, делая ваш ComplicatedWrapperFactory единственным способом создания новых сложных реализаций.

Другие вопросы по тегам