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? 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
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.
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.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.
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