2011-04-01 13 views
12

Hasta ahora, utilicé Google Guice 2. Al migrar a guice 3.0, tuve problemas con las fábricas de inyección asistida. Asumir el siguiente códigoProblema con el tipo de devolución genérico en fábrica de inyección asistida por 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)); 
    } 
} 

Si bien la creación del inyector, me sale el siguiente excepción:

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) 

Con el creador de inyección asistida de guice 2 mi configuración funciona:

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

El único solución alternativa que encontré hasta ahora es eliminar el parámetro genérico del tipo de devolución del método de fábrica:

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

¿Alguien sabe por qué a Guice 3 no le gusta el parámetro genérico en el método de fábrica o lo que generalmente no entendí acerca de las fábricas de inyección asistida? ¡Gracias!

+0

Me pregunto si debería pasar un 'TypeLiteral >' en lugar de 'Payment.class' en el' implemento'? – Jeremy

+0

@Jeremy Heiler Gracias, pero ¿cómo harías eso? 'TypeLiteral' no tiene un constructor público y si usas' TypeLiteral.get (Payment.class) ', obtienes la misma excepción. – kraftan

+0

Quizás esto? 'TypeLiteral.get (Types.newParameterizedType (Payment.class, Currency.class));' – Jeremy

Respuesta

11

Hay dos problemas con su código anterior.

Primero, RealPayment implementa Payment<SwissFrancs>, pero devuelve Payment<Currency>. No se puede devolver un Payment<SwissFrancs> desde un método que devuelve Payment<Currency>. Si cambia el tipo de devolución de create a Payment<? extends Currency>, entonces RealPayment funcionará (porque es un Payment para algo que se extiende a Currency).

En segundo lugar, SÍ necesita utilizar la versión de implement que toma un TypeLiteral como primer argumento. La forma de hacerlo es usar una clase interna anónima. Para representar `pago' se puede utilizar

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

consulte el Javadoc para que TypeLiteral constructor para más información.

Cuestiones relacionadas