Как связать разные интерфейсы с помощью Google Guice?

Нужно ли создавать новый модуль с интерфейсом, привязанным к другой реализации?

Chef newChef = Guice.createInjector(Stage.DEVELOPMENT, new Module() {
     @Override
      public void configure(Binder binder) {
        binder.bind(FortuneService.class).to(FortuneServiceImpl.class);
      }

    }).getInstance(Chef.class);

Chef newChef2 = Guice.createInjector(Stage.DEVELOPMENT, new Module() {
  @Override
  public void configure(Binder binder) {
    binder.bind(FortuneService.class).to(FortuneServiceImpl2.class);
  }

}).getInstance(Chef.class);

Я не могу коснуться Класса Повара, ни Интерфейсов. Я всего лишь клиент, привязывающий шеф-повар FortuneService к различным интерфейсам во время выполнения.

3 ответа

Решение

Take выглядит как раздел " Ножки робота ", описанный в FAQ по Guice. "Как создать робота с двумя объектами Leg, левым с инъекцией LeftFoot, а правым с RightFoot". Но только один класс ног, который повторно используется в обоих контекстах.

Есть решение PrivateModules. Он использует два отдельных закрытых модуля: один @Left и @Right. Каждый из них имеет привязку для аннотированного класса Foot.class и Leg.class и предоставляет привязку для аннотированного класса Leg.class:

class LegModule extends PrivateModule {
  private final Class<? extends Annotation> annotation;

  LegModule(Class<? extends Annotation> annotation) {
    this.annotation = annotation;
  }

  @Override protected void configure() {
    bind(Leg.class).annotatedWith(annotation).to(Leg.class);
    expose(Leg.class).annotatedWith(annotation);

    bindFoot();
  }

  abstract void bindFoot();
}

... и склеить все это вместе:

  public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new LegModule(Left.class) {
          @Override void bindFoot() {
            bind(Foot.class).toInstance(new Foot("leftie"));
          }
        },
        new LegModule(Right.class) {
          @Override void bindFoot() {
            bind(Foot.class).toInstance(new Foot("righty"));
          }
        });
  }

Как вы решаете, какая реализация FortuneService требуется для Chef? Вы не можете привязать один и тот же интерфейс к разным реализациям, если у Guice нет способа различить их. Вы должны использовать что-то вроде этого.

bind(FortuneService.class).annotatedWith(Names.named("1").to(FortuneServiceImpl.class);
bind(FortuneService.class).annotatedWith(Names.named("2").to(FortuneServiceImpl2.class);

Для получения дополнительной информации см. Здесь

Я думаю, что вы можете использовать @Provides аннотаций. Смотрите здесь.

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