java - nfl - Inyectando genéricos con Guice.
que es el spring (1)
Estoy tratando de migrar un pequeño proyecto, reemplazando algunas fábricas con Guice (es mi primer ensayo de Guice). Sin embargo, estoy atascado cuando intento inyectar genéricos. Logré extraer un ejemplo de juguete pequeño con dos clases y un módulo:
import com.google.inject.Inject;
public class Console<T> {
private final StringOutput<T> out;
@Inject
public Console(StringOutput<T> out) {
this.out = out;
}
public void print(T t) {
System.out.println(out.converter(t));
}
}
public class StringOutput<T> {
public String converter(T t) {
return t.toString();
}
}
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(StringOutput.class);
bind(Console.class);
}
public static void main(String[] args) {
Injector injector = Guice.createInjector( new MyModule() );
StringOutput<Integer> out = injector.getInstance(StringOutput.class);
System.out.println( out.converter(12) );
Console<Double> cons = injector.getInstance(Console.class);
cons.print(123.0);
}
}
Cuando ejecuto este ejemplo, todo lo que tengo es:
Excepción en el hilo "main" com.google.inject.CreationException: errores de creación de Guice:
1) playground.StringOutput<T> cannot be used as a key; It is not fully specified.
at playground.MyModule.configure(MyModule.java:15)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354)
at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152)
at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105)
at com.google.inject.Guice.createInjector(Guice.java:92)
Intenté buscar el mensaje de error, pero sin encontrar sugerencias útiles. Más adelante en la sección de Preguntas frecuentes de Guice, me topo con una pregunta sobre cómo inyectar genéricos. Intenté agregar el siguiente enlace en el método de configure
:
bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>());
Pero sin éxito (mismo mensaje de error).
¿Puede alguien explicarme el mensaje de error y proporcionarme algunos consejos? Gracias.
Creo que el problema específico que está viendo es probablemente debido a la declaración de bind(Console.class)
. Debería usar un TypeLiteral
también. O, simplemente, no puede vincular ninguno de estos y JIT se encargará de usted, ya que los dos tipos involucrados aquí son clases concretas.
Además, debe recuperar la Console
con:
Console<Double> cons =
injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){}));
Edición: no es necesario vincular a una instancia solo porque está usando un TypeLiteral
. Usted puede simplemente hacer:
bind(new TypeLiteral<Console<Double>>(){});
Por supuesto, como dije anteriormente, puede saltarse eso en este caso y recuperar la Console
del inyector usando una Key
basada en el TypeLiteral
y la vinculación estaría implícita.