以下代码是一个工厂的示例,该工厂生成Bar<T>
给定Foo<T>
。工厂不关心T
是什么:对于任何类型T
,它可以从Bar<T>
生成Foo<T>
。
import com.google.inject.*;
import com.google.inject.assistedinject.*;
class Foo<T> {
public void flip(T x) { System.out.println("flip: " + x); }
}
interface Bar<T> {
void flipflop(T x);
}
class BarImpl<T> implements Bar<T> {
Foo<T> foo;
@Inject
BarImpl(Foo<T> foo) { this.foo = foo; }
public void flipflop(T x) { foo.flip(x); System.out.println("flop: " + x); }
}
interface BarFactory {
<T> Bar<T> create(Foo<T> f);
}
class Module extends AbstractModule {
public void configure() {
bind(BarFactory.class)
.toProvider(
FactoryProvider.newFactory( BarFactory.class, BarImpl.class )
);
}
}
public class GenericInject {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module());
Foo<Integer> foo = new Foo<Integer>();
Bar<Integer> bar = injector.getInstance(BarFactory.class).create(foo);
bar.flipflop(0);
}
}
当我运行代码时,我从Guice得到以下错误:
1) No implementation for BarFactory was bound.
at Module.configure(GenericInject.java:38)
2) Bar<T> cannot be used as a key; It is not fully specified.
我可以在Guice文档中找到泛型的唯一参考说明使用TypeLiteral
。但是我没有文字类型,我有一个与工厂无关的通用占位符。有什么提示吗?
答案 0 :(得分:4)
一种选择是手工编写BarFactory样板:
class BarImplFactory implements BarFactory {
public <T> Bar<T> create(Foo<T> f) {
return new BarImpl(f);
}
}
绑定变为
bind(BarFactory.class).to(BarImplFactory.class);
答案 1 :(得分:-1)
如果你认为guice是一个类似于spring的布线系统,那么连接一个通用实例并没有多大意义。您将特定实例连接到键,以便当另一个实例化类使用@Inject BarFactory标记某些内容时,您将获得特定的已创建实例。
由于您的实现是通用的,因此您没有提供足够的信息来注入特定实例。虽然我没有使用factoryprovider,但我的假设是你需要将Barfactory绑定到一个完全参数化的实例,例如BarImpl<Concrete>
而不是BarImpl)
顺便说一句,因为你要绑定BarFactory.class,如果你想绑定多个实例,你将不得不以某种方式使用它们,无论是通过名称,等等(没有检查语法,但是)
bind(BarFactory.class).annotatedWith(Names.named("name1"))
.toProvider(
or by generics, bind(BarFactory<Concrete>).toProvider...