到目前为止,我成功使用了google guice 2.在迁移到guice 3.0时,我遇到了辅助注入工厂的麻烦。假设以下代码
public interface Currency {}
public class SwissFrancs implements Currency {}
public interface Payment<T extends Currency> {}
public class RealPayment implements Payment<SwissFrancs> {
@Inject
RealPayment(@Assisted Date date) {}
}
public interface PaymentFactory {
Payment<Currency> create(Date date);
}
public SwissFrancPaymentModule extends AbstractModule {
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Payment.class, RealPayment.class)
.build(PaymentFactory.class));
}
}
在创建注入器时,我得到以下异常:
com.google.inject.CreationException: Guice creation errors:
1) Payment<Currency> is an interface, not a concrete class.
Unable to create AssistedInject factory. while locating Payment<Currency>
at PaymentFactory.create(PaymentFactory.java:1)
使用来自guice 2的辅助注射创建器,我的配置有效:
bind(PaymentFactory.class).toProvider(
FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));
到目前为止,我发现的唯一解决方法是从工厂方法的返回类型中删除泛型参数:
public interface PaymentFactory {
Payment create(Date date);
}
有谁知道,为什么guice 3不喜欢工厂方法中的泛型参数或者我通常对辅助注入工厂的误解?谢谢!
答案 0 :(得分:12)
上面的代码存在两个问题。
首先,RealPayment
实施Payment<SwissFrancs>
,但PaymentFactory.create
返回Payment<Currency>
。无法从返回Payment<SwissFrancs>
的方法返回Payment<Currency>
。如果您将create
的返回类型更改为Payment<? extends Currency>
,那么RealPayment
将起作用(因为对于扩展Payment
的内容,它是Currency
。
其次,您需要使用implement
作为其第一个参数的版本TypeLiteral
。这样做的方法是使用匿名内部类。要表示“付款”,您可以使用
new TypeLiteral<Payment<? extends Currency>>() {}
有关更多信息,请参阅该TypeLiteral
构造函数的Javadoc。