Guice:注入一个字符串的ArrayList

时间:2015-06-12 11:50:42

标签: java arraylist guice inject

我正试图在Guice的帮助下注入ArrayList Stringpublic class UIProviderModule extends ProviderServiceModule { private ArrayList<String> requestedServices; public UIProviderModule(ArrayList<String> requestedServices) { this.requestedServices = requestedServices; } @Override protected void configure() { bindConstant().annotatedWith(Names.named(Constants.REQ_SERVICES)).to(requestedServices); bind(IParser.class).to(UIParser.class); super.configure(); } } 。我想显示一个带有许多RadioButtons的面板(例如),用户可以在其中选择一些要激活的服务。

选择后,我想获取所选服务的所有名称并将其添加到列表中,并将此列表注入负责创建服务的经理。这是一个例子:

Module

我见过很多关于Multibindings以及提供商的帖子,但我不明白这对我有什么帮助。我只是想检索名称,因为我不使用必须绑定到接口的类。我错过了什么吗?

注意:我知道这可能不是使用Guice 的好方法,因为我将列表绑定到type

2 个答案:

答案 0 :(得分:6)

这很容易做Guice:

bind(new TypeLiteral<List<String>>() {})
    .annotatedWith(Names.named(Constants.REQ_SERVICES))
    .toInstance(requestedServices);

请注意,为了在不使用Java擦除泛型的情况下绑定List<String>,您将创建一个短命的匿名内部类型(TypeLiteral的子类,其中包含空主体{})。您还可以使用toInstance

让模块采用用于绑定的参数没有任何问题,而且当在一个地方轻松收集所有绑定时,我更喜欢使用Multibindings。

请注意,您接受的ArrayList<String>是可变的,因此如果您在多个地方注入此内容,则一个消费者可以为其他人永久更改列表。使用Guava的ImmutableList.copyOf(list)Collections.unmodifiableList(list)可能更有意义(尽管如果模块创建者稍后更改传入列表,后者仍会让列表更改。)

关于您建议的应用程序生命周期,请记住Guice的绑定在创建注入器后应保持或多或少的不变。您描述的生命周期可能有两种方式:

  • 在没有Guice帮助的情况下显示您的对话框,然后使用所选选项创建一个Injector
  • 注入所有选项的List<String>,显示对话框,然后传递列表
  • 使用所有选项注入List<String>,显示对话框,然后创建包含所选选项列表的子注入器

然而,所有这些都是可行的,具体取决于您希望完整列表和选定列表在您的应用程序中的可访问性。

答案 1 :(得分:3)

我认为你误解了模块应该如何运作。

模块不创建对象,模块定义在需要时如何创建对象的规则。

MapBinder有用的原因是您要在单选按钮列表中定义所有服务,然后使用注入的地图激活您需要的服务。

这里有一些代码来说明我的意思:

public class ServiceModule extends AbstractModule {
  protected void configure() {
    MapBinder<String, Service> mapbinder
        = MapBinder.newMapBinder(binder(), String.class, Service.class);
    mapbinder.addBinding("service1").to(Service1.class).in(Singleton.class);
    mapbinder.addBinding("service2").to(Service2.class);
    // Define ALL the services here, not just the ones being used.
    // You could also look this up from a ClassLoader or read from a configuration file if you want
  }
}

然后,将MapBinder注入您的ServiceManager类 - 模块:

public class ServiceManager {
  private final Map<String, Service> serviceMap;

  @Inject
  public ServiceManager(Map<String, Service) serviceMap) {
    this.serviceMap = serviceMap;
  }

  // This is just one way to do it. It depends on how your UI works
  public void startAll(List<String> serviceList) {
    for(String serviceName : serviceList) {
      serviceMap.get(serviceName).start();
    }
  }
}