有一个使用Guice的子类的通用提供程序?

时间:2013-01-18 16:21:49

标签: dependency-injection guice

我正在尝试为所有子类实现一个公共提供程序,想象一些模式: SuperComponent.classComponentA.classComponentB.class的父级。 我有提供者:

    @Provides
<T extends SuperComponent> List<T> providesComponents(Provider<T> provider) {
    List<T> componentList = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        componentList.add(provider.get());
    }
    return componentList;
}

这个想法是在需要另一个类的构造函数中的对象List<ComponentA>和/或List<ComponentB>时调用此提供程序。 想象一下:

public class ResourceManager {

List<ComponentA> componentAList;
List<ComponentB> componentBList;    

@Inject
public ResourceManager(List<ComponentA> componentAList, List<ComponentB> componentBList) {
    this.componentAList = componentAList;
            this.componentBList = componentBList;
}

我收到错误说:

1) com.google.inject.Provider<T> cannot be used as a key; It is not fully specified.

我怎样才能让它发挥作用?我知道我可以为List<ComponentA>List <ComponentB>创建不同的提供者,但我需要它,因为在现实中组件的数量远大于2 ...

1 个答案:

答案 0 :(得分:0)

我不认为有一个很好的内置方法来处理这个问题 - Guice可以绑定很多,或检查和操作它的绑定,但没有良好的接口来创建元级绑定。不过你确实有几个选择:

  1. 通过提供商将列表构建留给消费者:

    public static <T> List<T> createList(Provider<T> provider) {
      List<T> list = new ArrayList<T>();
      for (int i = 0; i < 5; i++) {
        list.add(provider.get());
      }
      return list;
    }
    
    @Inject MyConsumer(Provider<Foo> depProvider) {
      List<Foo> myFoos = createList(depProvider);
    }
    
  2. 列出您需要绑定的类,并使用configure方法创建提供者:

    public class MyModule extends AbstractModule {
      public void configure() {
        List<Class<?>> classList = Lists.newArrayList(Class1.class, Class2.class);
        for (Class<?> clazz : classList) {
          bind(listOf(clazz)).toProvider(new ComponentListProvider<?>(getProvider(clazz)));
        }
      }
    
      private static <T> Key<List<T>> listOf(Class<T> clazz) {
        return new Key<List<T>>() {};
      }
    
      private static class ComponentListProvider<T> implements Provider<List<T>>() {
        private final Provider<T> wrappedProvider;
    
        ComponentListProvider(Provider<T> wrappedProvider) {
          this.wrappedProvider = wrappedProvider;
        }
    
        @Override public List<T> get() {
          return createList(wrappedProvider);
        }
      }
    }
    

    这使用了getProvider,这是一种非常方便的方法,可以检索键入的Provider,该Injector会在创建{{1}}之后立即生效(但不会在之前)。

  3. 使用Guice SPI通过迭代模块中的每个绑定来编写执行上述任一操作的模块。

  4. 希望有所帮助!