Подтвердить что ты не робот

Передача параметра конструктору с помощью Guice

У меня есть фабрика, как показано ниже,

public final class Application {

    private static IFoo foo;

    public static IFoo getFoo(String bar)
    {
        // i need to inject bar to the constructor of Foo
        // obvious i have to do something, not sure what
        Injector injector = Guice.createInjector();
        logger = injector.getInstance(Foo.class);
        return logger;              
    }

}

Это определение Foo:

class Foo
{
   Foo(String bar)
   {

   }

}

ХОРОШО. Я не уверен, как я могу передать этот параметр конструктору Foo с помощью Guice?

Есть идеи?

4b9b3361

Ответ 1

Все ответы "Guice Constructor Parameter" в некотором роде кажутся неполными. Вот полное решение, включая использование:

interface FooInterface{
  String getFooName();
}

//Аннотируем конструктор и вспомогательные параметры в классе реализации

class Foo implements FooInterface {
   String bar;

   @Inject
   Foo(@Assisted String bar)
   {
      this.bar = bar;
   }

   // return the final name
   getFooName(){
     return this.bar;
   }

}

//Создать заводской интерфейс с методом create(), который принимает только вспомогательные параметры.

//Интерфейс FooFactory не имеет явного класса реализации (Guice Magic)

interface FooFactory{
   Foo create(String bar);
}

//Привязать эту фабрику к провайдеру, созданному AssistedInject

binderModule implements Module{

 void configure(Binder binder) {
   binder.install(new FactoryModuleBuilder()
         .implement(FooInterface.class, Foo.class)
         .build(FooFactory.class));
 }
}

//Теперь используем это:

class FooAction{

   @Inject private FooFactory fooFactory;

   doFoo(){
      // Send bar details through the Factory, not the "injector" 
      Foo f = fooFactory.create("This foo is named bar. How lovely!");
      f.getFooName(); // "This foo is named bar. How lovely!"
   }
}

Здесь много полезной информации: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html.

Ответ 2

То, что вы, вероятно, ищете, - это использовать Guice factory. Особенно удобно использовать AssistedInject, но они имеют ручной пример в верхней части страницы. Короче говоря, для примера с ручным является то, что вы получаете factory под нестатический метод getFoo, чтобы передать все параметры, которые вам нужны, и построить объект оттуда.

Это не будет работать напрямую, если у вас есть метод перехвата в Foo, но он будет работать во многих других случаях.

Чтобы использовать AssistedInject, который для меня имеет несколько более чистую семантику и означает меньше ручной проводки, вам понадобится расширение guice-assistedinject в пути к классам, тогда при создании Foo (ну, FooImpl мы должны использовать интерфейсы):

@Inject
public FooImpl(@Assisted String bar)
{
    this.baz = bar;
}

Затем вы создаете интерфейс FooFactory:

public interface FooFactory {
    public Foo create(String bar);
}

Затем в вашем графическом модуле:

install(new FactoryModuleBuilder()
    .implement(Foo.class, FooImpl.class)
    .build(FooFactory.class));

Вы можете проверить javadoc для FactoryModuleBuilder для примеров с более сложными фабриками.

Ответ 3

Я знаю, что это старая ветка, но сегодня я сам решил эту проблему. Мне нужно всего два или максимум три разных экземпляра 'Foo', и я действительно не хотел писать весь болгарный код Factory. Немного погуглив, я нашел этот веб-блог Stubbisms - Tonys. Я бы предложил это решение, которое идеально, если вы точно знаете, какие экземпляры вам нужны.

В модуле Guice:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic A");
        }
    });
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic B");
        }
    });

Или в Java 8:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));

И в конструкторе вашего сервиса, где вам нужны экземпляры Foo:

@Inject
public MyService (
    @Named("firstFoo") Foo firstFoo,
    @Named("secondFoo") Foo secondFoo) {
}

И Фу в моем случае:

public class FooImpl implements Foo {

    private String name;

    public FooImpl(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

Надеюсь, это поможет кому-то.

Ответ 4

Если этот класс является factory, он должен быть объектом, управляемым Guice, с не статическим методом getFoo, и метод getFoo будет использовать

new Foo(bar)

Не каждый класс должен быть создан Guice.

Также см. AssistedInject, чтобы избежать создания этого factory самостоятельно и позволить Guice создать его для вас.