Przekaż parametr do konstruktora za pomocą Guice

Mam fabrykę jak poniżej,

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;              
    }

}

To jest definicja Foo:

class Foo
{
   Foo(String bar)
   {

   }

}
OK. Nie jestem pewien, jak mogę przekazać ten parametr Foo constructor z Guice? Jakieś pomysły?
 30
Author: DarthVader, 2012-02-11

4 answers

Wszystkie odpowiedzi "Guice Constructor Parameter" wydają się być w jakiś sposób niekompletne. Oto kompletne rozwiązanie, w tym użycie:

interface FooInterface{
  String getFooName();
}

/ / Adnotacja konstruktora i wspomaganych parametrów na klasie implementacji

class Foo implements FooInterface {
   String bar;

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

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

}

/ / Utwórz interfejs fabryczny za pomocą metody create (), która pobiera tylko parametry wspomagane. // Foofactory interface doesn ' t have a explicit implementation class (Guice Magic)

interface FooFactory{
   Foo create(String bar);
}

// powiązać tę fabrykę z dostawcą utworzonym przez AssistedInject

binderModule implements Module{

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

/ / Teraz użyj:

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!"
   }
}

Wiele pomaga tutaj: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

 46
Author: DougA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 12:13:17

To, czego prawdopodobnie szukasz, to użycie fabryki Guice. Szczególnie łatwe z AssistedInject funkcjonalności, ale mają ręczny przykład na górze strony . W skrócie dla przykładu ręcznego jest to, że otrzymujesz fabrykę za pomocą niestatycznej metody getFoo, którą przekazujesz dowolne parametry do tego, czego potrzebujesz i stamtąd zbudujesz obiekt.

To nie będzie działać bezpośrednio, jeśli masz przechwytywanie metody w Foo, ale będzie działać w wielu innych przypadkach.

Aby użyć AssistedInject, które według mnie ma nieco czystszą semantykę i oznacza mniej ręcznego okablowania, potrzebujesz rozszerzenia guice-assistedinject w classpath, wtedy podczas tworzenia Foo (dobrze, FooImpl, powinniśmy używać interfejsów):

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

Następnie tworzysz FooFactory interfejs:

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

Następnie w module guice:

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

Możesz sprawdzić javadoc dla FactoryModuleBuilder na przykład z bardziej złożonymi fabrykami.

 8
Author: David H. Clements,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-11 16:51:53

Wiem, że to stary wątek, ale sam dziś trafiłem na ten temat. Potrzebuję tylko dwóch lub maksymalnie trzech różnych instancji " Foo " i naprawdę nie chciałem pisać całego kodu bolierplate fabryki. Przy odrobinie googlowania znalazłem ten Stubbisms-Tony ' s Weblog sugerowałbym To rozwiązanie, które jest idealne, jeśli wiesz dokładnie, jakich instancji potrzebujesz.

W module 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");
        }
    });

Lub w Javie 8:

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

I w konstruktorze swojej usługi, gdzie ty need Foo instances:

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

I Foo w moim przypadku:

public class FooImpl implements Foo {

    private String name;

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

    @Override
    public String getName() {
        return name;
    }
}
Mam nadzieję, że to komuś pomoże.
 5
Author: NejcT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 06:12:18

Jeśli ta klasa jest fabryczna, powinna być obiektem zarządzanym przez Guice, posiadającym niestatyczną metodę getFoo, a metoda getFoo użyłaby tylko

new Foo(bar)

Nie każda klasa musi być tworzona przez Guice.

Zobacz także AssistedInject , aby uniknąć tworzenia tej fabryki samodzielnie i pozwolić Guice stworzyć ją dla Ciebie.

 1
Author: JB Nizet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 17:16:52