Wstrzykiwanie kolekcji klas za pomocą Guice

Próbuję wprowadzić rzeczy z Google Guice 2.0 i mam następującą strukturę:

FooAction implements Action
BarAction implements Action

Mam wtedy ActionLibrary z następującym konstruktorem:

ActionLibrary (List<Action> theActions)

Kiedy żądam instancji ActionLibrary z Guice, chciałbym, aby Guice zidentyfikował obie zarejestrowane klasy akcji (FooAction, BarAction) i przekazał je do konstruktora. Motywacją jest to, że gdy dodam trzecią akcję BazAction, będzie to tak proste, jak rejestracja to w Module i zostanie automatycznie dodany do listy w konstruktorze.

Czy to możliwe?
 34
Author: durron597, 2010-12-10

2 answers

To, czego chcesz, to wielowątkowość . W szczególności, chcesz związać Set<Action> (nie List, ale {[3] } jest prawdopodobnie tym, czego naprawdę chcesz) w ten sposób:

Multibinder<Action> actionBinder = Multibinder.newSetBinder(binder(), Action.class);
actionBinder.addBinding().to(FooAction.class);
actionBinder.addBinding().to(BarAction.class);

Wtedy możesz @Inject Set<Action> gdziekolwiek.

 45
Author: ColinD,
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
2015-07-08 14:38:27

Pozwól, że pokażę Ci, co uważam za jeszcze lepszy sposób multibinding rzeczy. Jeśli chcesz, aby Action S były wtyczkowe i pozwalały każdemu je dodawać, często przydatne jest zapewnienie prostego Module dla kogoś, kto będzie używał, który ukrywa potrzebę utworzenia instancji Multibinder. Oto przykład:

public abstract class ActionModule extends AbstractModule {
  private Multibinder<Action> actionBinder;

  @Override protected void configure() {
    actionBinder = Multibinder.newSetBinder(binder(), Action.class);
    configureActions();
  }

  /**
   * Override this method to call {@link #bindAction}.
   */
  protected abstract void configureActions();

  protected final LinkedBindingBuilder<Action> bindAction() {
    return actionBinder.addBinding();
  }
}

Dlaczego tak jest lepiej? Pozwala na użycie ActionModule z dowolnego miejsca, aby dodać więcej Actionza pośrednictwem standardowego interfejsu API. Myślę, że jest bardziej czytelny. Oto przykładowe użycie:

public final class MyStandardActionModule extends ActionModule() {
  @Override protected void configureActions() {
    bindAction().to(FooAction.class);
    bindAction().to(BarAction.class);
    // If you need to instantiate an action through a Provider, do this.
    bindAction().toProvider(BazActionProvider.class);
    // You can also scope stuff:
    bindAction().to(MySingletonAction.class).in(Singleton.class);
  }
}

Ten wzór użycie Module do ukrycia multibindera jest używane w kodzie Guice. To trochę pracy z góry, ale utrzymuje porządek. Możesz również zrobić coś podobnego dla MapBinder, jeśli potrzebujesz. Pamiętaj, że możesz utworzyć dowolną liczbę ActionModule s, ile chcesz.

 23
Author: Tom,
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
2015-10-29 12:58:57