Guice无界通用绑定

时间:2013-04-17 16:21:11

标签: java generics guice

我想提供通用实例,而无需在模块实现中明确声明通用参数。

假设我有一个非常优化的Map实现,并希望每个人都使用它。

class MyVeryOptimizedHashMap<K, V> implements Map<K, V> {}

我知道,使用后不是最好的设计模式,但为了这个例子,这是一个有效的要求:

class SomeInjectee {
  @Inject
  private Map<String, Integer> myMap;
}

在模块声明工作之后,将此实例绑定到我选择的提供者:

class GenericMapModule extends AbstractModule {
  protected void configure() {
    bind(new TypeLiteral<Map<String, Integer>>() {}).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap<String, Integer>>>() {});
  }
}

问题是我必须明确说明泛型类型参数,我不可能对所有可能的类型做:

class SomeOtherInjectee{
  @Inject
  private Map<SomeUnknownKey, Long> myMap;
}

这解决了我的问题,但不是很优雅:

class GenericModule extends AbstractModule {
  protected void configure() {
    bind(new TypeLiteral<Map<?, ?>>() {}).toProvider(new Provider<Map<?,?>>() {
      public Map<?, ?> get() {
        return new MyVeryOptimizedHashMap();
      }
    });
  }
}

class SomeOtherInjectee {
  private Map<SomeUnknownKey, Long> myMap;

  @Inject
  void setMap(Map<?, ?> mapInstance) {
    myMap = (Map<SomeUnknownKey, Long>) mapInstance;
  }
}

我正在寻找的是:

class GenericModule extends AbstractModule {
  protected void configure() {
    bind(TypeLiteral.anyGenericVariant(Map.class)).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap>>(){});        
  }
}

1 个答案:

答案 0 :(得分:0)

如果适用于您的情况,我尝试使用静态实用方法。

class SomeOtherInjectee {
    private Map<SomeUnknownKey, Long> myMap = newOptimizedMap();

如果这不适用,那么正如您所见,Guice在泛型方面非常精确,即每个通用变体代表一种独特的绑定。因此anyGenericVariant实际上必须列出所有可能的变体并提前进行绑定。疯狂。

在这种情况下,您可以使用TypeListener注册自定义注入。它看起来像

class SomeOtherInjectee {
    @InjectOptimizedMap private Map<SomeUnknownKey, Long> myMap;

或者你做的任何自定义注入注释。

有关如何进行自定义注射的信息,请参阅here for the full example and explanation