【发布时间】:2015-08-05 17:29:36
【问题描述】:
[Guice 4.0]
我想为泛型类提供一个接口,并通过 Guice 在依赖注入中使用它。 对于下面列出的代码,我收到以下错误:
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Could not find a suitable constructor in com.ulmon.fsqtransit.guicetest.Class1. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
at com.ulmon.fsqtransit.guicetest.Class1.class(Class1.java:14)
at com.ulmon.fsqtransit.guicetest.Module.configure(Module.java:14)
--
public class Class1<T1 extends Number, T2 extends Number>
implements InterfClass1<T1, T2> {
public static final String ANNOT1 = "ANNOT1";
public static final String ANNOT2 = "ANNOT2";
private T1 t1;
private T2 t2;
// for the factory
@AssistedInject
public Class1(
@Assisted(Class1.ANNOT1) T1 t1,
@Assisted(Class1.ANNOT2) T2 t2
) {
this.t1 = t1;
this.t2 = t2;
}
public T1 getT1() {
return t1;
}
public T2 getT2() {
return t2;
}
}
public class Module extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<InterfClass1<Integer, Integer>>(){})
.to(new TypeLiteral<Class1<Integer, Integer>>(){});
}
public static void main(String[] args) {
Injector inj = Guice.createInjector(new Module());
}
}
是什么导致了这个错误?
编辑后
让我们添加工厂并修改模块(从模块中删除InterfClass1接口):
public interface Class1Factory<T1 extends Number, T2 extends Number> {
public Class1<T1, T2> createClass1(
@Assisted(Class1.ANNOT1) T1 t1,
@Assisted(Class1.ANNOT2) T2 t2
);
}
public class Module extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder()
.build(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
}
public static void main(String[] args) {
Injector inj = Guice.createInjector(new Module());
Class1Factory f = inj.getInstance(Key.get(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
f.createClass1(10, 11.0);
}
}
效果很好!
现在让我们合并接口:
public class Module extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<InterfClass1<Integer, Double>>(){})
.to(new TypeLiteral<Class1<Integer, Double>>(){});
install(new FactoryModuleBuilder()
.build(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
}
public static void main(String[] args) {
Injector inj = Guice.createInjector(new Module());
Class1Factory f = inj.getInstance(Key.get(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
f.createClass1(10, 11.0);
}
}
我们得到:
1) Could not find a suitable constructor in com.ulmon.fsqtransit.guicetest.Class1. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
at com.ulmon.fsqtransit.guicetest.Class1.class(Class1.java:15)
at com.ulmon.fsqtransit.guicetest.Module.configure(Module.java:14)
好吧,不管报错,我们也改一下工厂:
public interface Class1Factory<T1 extends Number, T2 extends Number> {
public InterfClass1<T1, T2> createClass1(
@Assisted(Class1.ANNOT1) T1 t1,
@Assisted(Class1.ANNOT2) T2 t2
);
}
我们得到:
1) Could not find a suitable constructor in com.ulmon.fsqtransit.guicetest.Class1. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
at com.ulmon.fsqtransit.guicetest.Class1.class(Class1.java:15)
at com.ulmon.fsqtransit.guicetest.Module.configure(Module.java:14)
2) com.ulmon.fsqtransit.guicetest.InterfClass1<java.lang.Integer, java.lang.Double> is an interface, not a concrete class. Unable to create AssistedInject factory.
while locating com.ulmon.fsqtransit.guicetest.InterfClass1<java.lang.Integer, java.lang.Double>
at com.ulmon.fsqtransit.guicetest.Class1Factory.createClass1(Class1Factory.java:1)
但是,如果我删除模块中接口和类之间的关系并将此关系添加到工厂的规范中,我不会收到错误:
public class Module extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(new TypeLiteral<InterfClass1<Integer, Double>>(){}
, new TypeLiteral<Class1<Integer, Double>>(){})
.build(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
}
public static void main(String[] args) {
Injector inj = Guice.createInjector(new Module());
Class1Factory f = inj.getInstance(Key.get(new TypeLiteral<Class1Factory<Integer, Double>>(){}));
f.createClass1(10, 11.0);
}
}
效果很好!
为什么 Guice 会有这种奇怪的行为?为什么无论工厂如何,我都无法将接口与实现类相关联?
【问题讨论】:
标签: java generics inheritance dependency-injection guice