绑定到TypeLiteral是谷歌guice中的好或坏做法

时间:2012-04-26 10:28:14

标签: java dependency-injection guice

Google guice使用new TypeLiteral<C<T>>() {}来克服我们无法使用C<T>.class这一事实。

现在通常如下:

bind(new TypeLiteral<C<T>>() {}).to(MyCSubclassTypedToT.class);

想象一下不同的场景。我们有一个通用接口,我们想要注入,我们的实现由泛型类提供。

Guice允许你这样做:

bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});

另一种方法是扩展MyGenericClass,如下所示:

MyTypedClass extends MyGenericClass<T>

然后像这样绑定它:

bind(MyGenericInterface<T>>() {}).to(MyTypedClass.class);

如果MyGenericInterface被注入了很多(尽管有不同的类型),每次我注入它都使用MyGenericClass,后一种方法导致过于冗长的代码。因此,我倾向于使用前者。

我非常希望听到其他人关于在guice绑定的to子句中使用TypeLiteral的意见。我担心我可能会选择做空,因此不会看到这种方法的缺陷。

2 个答案:

答案 0 :(得分:2)

在这种情况下,使用TypeLiteral进行通用实现会让我觉得好多了。

让我这样说:“如果你没有使用Guice,子类MyTypedClass会不会存在?” Guice的基本准则是:您不必更改实现类以适应DI框架(除了@Inject注释之外)。

你从子类化具体而又通用的类中获得了什么?一个很大的损失是你必须在所有子类中复制MyGenericClass的构造函数。总而言之,它似乎是额外的代码而没有太大的收获。

总而言之,使用TypeLiteral通常没有任何问题。如果它在绑定子句的.to(...)部分(而不是bind(...)),它甚至不会影响Module绑定的公开可见部分,所以我不喜欢我认为有很多事要担心。

答案 1 :(得分:1)

通常有两种情况:

  1. 您希望将MyGenericInterface的所有实现绑定到MyGenericClass
  2. 您希望基于其类型
  3. 绑定MyGenericInterface的实现

    对于第一种情况,bind(MyGenericInterface).to(MyGenericClass);就足够了,更简单易懂。

    对于第二个场景,您需要将特定类的实现绑定到特定的实现,TypeLiteral将发挥作用。

    此外,您的问题中的代码不清楚T是实际类还是泛型类型。如果是通用类型,

    bind(new TypeLiteral<MyGenericInterface<T>>() {}).to(new TypeLiteral<MyGenericClass<T>>() {});

    MyTypedClass extends MyGenericClass<T>

    不会编译,因为没有提供某些实际的类。