2010-02-01 12 views
27

Situación: necesito la creación de instancias de dependencia diferida en algunos FooClass, por lo que paso Injector a la clase como un parámetro de constructor.¿Cómo inyectar el inyector?

private final Injector m_injector; 

public FooClass(@Named("FooInjector") Injector injector) { 
m_injector = injector; 
} 

Pero guice no permite unir las clases principales (inyectores, módulos, etc.). ¿Cuál es la solución?

Respuesta

27

No debe utilizar el Injector directamente. En su lugar, pase el Provider<FooClass>. Además, debe inyectar al proveedor en los lugares donde usa FooClass.

private final Provider<FooClass> provider; 

@Inject 
public ClassWhereFooIsUsed(Provider<FooClass> provider) { 
    this.provider = provider; 
} 

.... somewhere else 
FooClass f = provider.get(); // This is lazy 
+0

Thx! Lo intentaré para la inicialización perezosa. Pero, ¿realmente no hay forma de inyectar Injector? –

+6

Puede obtener el inyector con '@Inject Injector Injector', puede estar en el constructor/campo/método. – gpampara

+0

¿Has probado esto? ¿Cómo configurar el módulo? Guice restringe el enlace a las clases principales: "No se permite el enlace con el tipo de marco de control central: Inyector". –

7

Como @gpampara dicho, Provider<T> se debe utilizar para la inicialización perezosa/opcional. Además, como dije en mi respuesta a su otra pregunta, debería evitar las referencias al Injector en su código en casi todos los casos.

Dicho esto, en una clase creada por Guice, el Injector que está creando el objeto se puede inyectar simplemente declarando una dependencia en Injector. El Injector está automáticamente disponible para inyección sin que usted declare ningún enlace.

Si inyecta el Injector, debe pensar en POR QUÉ desea hacer eso. ¿Por qué no declaras dependencias en las interfaces/clases de las que depende la clase? Es tan fácil agregar una nueva dependencia al constructor como recuperar una instancia de alguna dependencia a través del Injector en otro lugar de su código, y hace que el código sea mucho más comprensible también.

+0

Re: "POR QUÉ quieres hacer eso" - Por ejemplo, quiero crear proxies dinámicos sobre la marcha después de bootstrap. mi pregunta sobre esto: http://stackoverflow.com/questions/34252268/best-practice-for-creating-dynamic-proxies-with-guice –

8

Como otros ya han respondido, simplemente puede usar @Inject Injector porque Guice define el enlace en sí.

Normalmente solo necesita un inyector en su aplicación, y una variable estática es una forma aún más fácil de almacenar y acceder a un singleton que inyectarlo. En nuestra aplicación web, usamos stripes-guicer y obtenemos el inyector de su método estático GuiceInjectorFactory.getInjector() cuando lo necesitamos (en nuestro interceptor de Hibernate, por ejemplo).

Estoy un poco desconcertado por el consejo de que "no deberías usar Injector directamente". ¿De qué otro modo podría obtener una instancia inyectada excepto llamando a injector.getInstance() o injector.injectMembers()? No hay forma. Sí, puede definir métodos de Proveedor, pero nunca se llamarán a menos que estén en algún lugar, algo usa un Inyector. Sí, hay módulos que usan el Inyector como el ServletModule; usted tiene que crear el inyector usted mismo, pero luego puede dejarlo en el ServletModule.

Por lo tanto, en algunas circunstancias puede evitar el uso directo del inyector, pero eso no significa que "no debería" usarlo. Si está utilizando Guice solo sin ningún módulo opcional, entonces "debería" estar usando un inyector en todas partes porque no hay otra forma de activar la inyección. (Creo que los desarrolladores que pasan todo el día escribiendo código dentro de frameworks a veces se olvidan de que algunas personas crean sus propios objetos).

+3

No estoy seguro de haber entendido la razón de ser de Guice. Pretende explícitamente evitar el uso de campos y estado estáticos, y muy pocas veces se debe hacer una referencia directa al inyector. Obtiene instancias inyectadas declarando dependencias con @Inject, en lugar de llamar a 'getInstance()' en el inyector. –

+12

Mi único punto (que hice con bastante vehemencia) es que tienes que empezar en alguna parte; es un problema de gallina y huevo. No puede * solo * decorar métodos con @Inject y esperar que ocurra cualquier cosa. Algo, en algún lugar, debe llamar a injector.getInstance() o injector.injectMembers() para iniciarlo todo. –

Cuestiones relacionadas