2011-04-01 57 views
12

到目前爲止,我成功地使用了google guice 2.在遷移到guice 3.0時,我遇到了輔助注入工廠的麻煩。假設下面的代碼guice輔助注入工廠中的通用返回類型的問題

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) 

隨着輔助注射創作者從吉斯2我的配置工作:

bind(PaymentFactory.class).toProvider(
FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class)); 

唯一我發現迄今爲止的解決方法是從工廠方法的返回類型中刪除通用參數:

public interface PaymentFactory { 
    Payment create(Date date); 
} 

有誰知道,爲什麼guice 3不喜歡工廠方法中的泛型參數或我通常誤解了輔助注入工廠?謝謝!

+0

我想知道你是否應該將'PaymentLlassral >'而不是'Payment.class'傳遞給'implement'? – Jeremy 2011-04-01 14:21:38

+0

@Jeremy Heiler謝謝,但你會怎麼做? 'TypeLiteral'沒有公共構造函數,如果使用'TypeLiteral.get(Payment.class)',你會得到相同的異常。 – kraftan 2011-04-01 18:50:21

+0

也許這樣?'TypeLiteral.get(Types.newParameterizedType(Payment.class,Currency.class));' – Jeremy 2011-04-01 18:54:09

回答

11

上面的代碼有兩個問題。

首先,RealPayment執行Payment<SwissFrancs>,但PaymentFactory.create返回Payment<Currency>。 A Payment<SwissFrancs>不能從返回Payment<Currency>的方法返回。如果您將退貨類型create更改爲Payment<? extends Currency>,那麼RealPayment將起作用(因爲它是Payment,用於延伸Currency的某些內容)。

其次,您需要使用implement版本,它將TypeLiteral作爲其第一個參數。做到這一點的方法是使用匿名內部類。爲了表示'支付」,你可以使用

new TypeLiteral<Payment<? extends Currency>>() {} 

見該TypeLiteral構造的Javadoc以獲取更多信息。