java 使用 Guice 注入类集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4410712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:14:36  来源:igfitidea点击:

Injecting Collection of Classes with Guice

javaguice

提问by Scruffers

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

我正在尝试使用 Google Guice 2.0 注入内容,并且具有以下结构:

FooAction implements Action
BarAction implements Action

I then have an ActionLibrary with the following constructor:

然后我有一个带有以下构造函数的 ActionLibrary:

ActionLibrary (List<Action> theActions)

When I request an instance of ActionLibrary from Guice, I would like Guice to identify both of the registered Action classes (FooAction, BarAction) and pass them into the constructor. The motivation here being that when I add a third action BazAction, it would be as simple as registering it in the Module and it would automatically be added to the list in the constructor.

当我从 Guice 请求 ActionLibrary 的实例时,我希望 Guice 识别两个已注册的 Action 类(FooAction、BarAction)并将它们传递给构造函数。这里的动机是当我添加第三个动作 BazAction 时,就像在模块中注册它一样简单,它会自动添加到构造函数的列表中。

Is this possible?

这可能吗?

回答by ColinD

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

你想要的是Multibindings。具体来说,您想像这样绑定 a Set<Action>(不是 a List,但 aSet可能是您真正想要的):

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

Then you can @Injectthe Set<Action>anywhere.

然后你可以@InjectSet<Action>任何地方。

回答by Tom

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 Modulefor someone to use that hides needing to instantiate the Multibinder. Here's an example:

让我向您展示我认为更好的多重绑定方法。如果您希望Actions 可插入并让任何人添加它们,那么提供一个简单的Module供某人使用的隐藏需要实例化Multibinder. 下面是一个例子:

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 ActionModulefrom anywhere to add more Actions via the standard binding API. I think it's more readable. Here's an example usage:

现在为什么这更好?它允许某人ActionModule从任何地方使用 anAction通过标准绑定 API添加更多s。我认为它更具可读性。这是一个示例用法:

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 Moduleto 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 MapBinderif you need to. Keep in mind you can instantiate as many ActionModules as you want.

这种使用 aModule隐藏 multibinder 的模式在 Guice 代码中使用。这是一些前期工作,但可以保持干净。MapBinder如果需要,您也可以为 a 做类似的事情。请记住,您可以根据需要实例化任意数量的ActionModules。