guice辅助注射工厂中通用返回类型的问题

kra*_*tan 13 java guice guice-3

到目前为止,我成功地使用了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));
    }
}
Run Code Online (Sandbox Code Playgroud)

在创建注入器时,我得到以下异常:

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)
Run Code Online (Sandbox Code Playgroud)

使用来自guice 2的辅助注射创建器,我的配置有效:

bind(PaymentFactory.class).toProvider(
FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));
Run Code Online (Sandbox Code Playgroud)

到目前为止我找到的唯一解决方法是从工厂方法的返回类型中删除泛型参数:

public interface PaymentFactory {
    Payment create(Date date);
}
Run Code Online (Sandbox Code Playgroud)

有谁知道,为什么guice 3不喜欢工厂方法中的泛型参数或我通常对辅助注入工厂的误解?谢谢!

小智 12

上面的代码有两个问题.

首先,RealPayment实现Payment<SwissFrancs>,但PaymentFactory.create返回Payment<Currency>.一个Payment<SwissFrancs>无法从返回一个方法返回Payment<Currency>.如果你改变createto 的返回类型Payment<? extends Currency>,那么RealPayment将起作用(因为它是一个Payment扩展的东西Currency).

其次,你需要使用的版本的implement,需要一个TypeLiteral作为第一个参数.这样做的方法是使用匿名内部类.要表示"付款",您可以使用

new TypeLiteral<Payment<? extends Currency>>() {}
Run Code Online (Sandbox Code Playgroud)

有关TypeLiteral更多信息,请参阅该构造函数的Javadoc .