Injecting Collection of Classes with Guice

后端 未结 2 928
醉酒成梦
醉酒成梦 2021-01-31 08:26

I\'m trying to inject things with Google Guice 2.0 and I have the following structure:

FooAction implements Action
BarAction implements Action

相关标签:
2条回答
  • 2021-01-31 09:07

    What you want for this is Multibindings. Specifically, you want to bind a Set<Action> (not a List, but a Set is probably what you really want anyway) like this:

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

    Then you can @Inject the Set<Action> anywhere.

    0 讨论(0)
  • 2021-01-31 09:28

    Let me show you what I consider an even better way of multibinding things. If you want Actions to be pluggable and let anyone add them, it's often useful to provide a simple Module for someone to use that hides needing to instantiate the Multibinder. Here's an example:

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

    Now why is this better? It allows someone to use an ActionModule from anywhere to add more Actions via the standard binding API. I think it's more readable. Here's an example usage:

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

    This pattern of using a Module to hide the multibinder is used in Guice code. It's a little work up front, but keeps things clean. You can also do something similar for a MapBinder if you need to. Keep in mind you can instantiate as many ActionModules as you want.

    0 讨论(0)
提交回复
热议问题