example - @inject java
¿Cómo utilizar CDI para inyección de parámetros de método? (5)
Esa característica de CDI se denomina "método de inicialización". La sintaxis difiere de su código en que todo el método está anotado con @Inject
, los parámetros del método pueden ser anotados por los calificadores para seleccionar un bean específico. La sección 3.9 de JSR 299 muestra el siguiente ejemplo, donde @Selected
es un calificador que se puede omitir si solo hay una implementación de bean.
@Inject
void setProduct(@Selected Product product) {
this.product = product;
}
Tenga en cuenta que
La aplicación puede llamar directamente a los métodos de inicialización, pero el contenedor no pasará ningún parámetro al método.
¿Es posible usar CDI para inyectar parámetros en las llamadas de método? El comportamiento esperado sería similar a la inyección de campo. Se busca el productor preferido y se utiliza el producto.
Lo que me gustaría hacer es esto:
public void foo(@Inject Bar bar){
//do stuff
}
o esto (con una sintaxis menos confusa):
public void foo(){
@Inject
Bar bar;
//do stuff
}
Esta sintaxis es ilegal en ambos casos. ¿Hay alguna alternativa? Si no, ¿sería una mala idea por alguna razón si fuera posible?
Gracias
EDITAR : es posible que no haya definido lo suficiente mis requisitos; me gustaría poder llamar directamente al método, dejando la inicialización de la variable de bar
al contenedor. La respuesta de Jörn Horstmann y Perception sugiere que no es posible.
Esta pregunta surgió cuando originalmente hice una búsqueda sobre este tema, y desde entonces aprendí que con el lanzamiento de CDI 1.1 (incluido en la especificación JavaEE 7), ahora hay una manera de hacer lo que el OP quería, parcialmente. Todavía no puedes hacer
public void foo(@Inject Bar bar){
//do stuff
}
pero puede "inyectar" una variable local, aunque no use @Inject
sino que busque la instancia inyectada mediante programación:
public void foo() {
Instance<Bar> instance = CDI.current().select(Bar.class);
Bar bar = instance.get();
CDI.current().destroy(instance);
// do stuff with bar here
}
Tenga en cuenta que el método select()
toma opcionalmente cualquier anotación de calificador que deba proporcionar. Buena suerte obteniendo instancias de java.lang.annotation.Annotation
sin embargo. Puede ser más fácil iterar a través de su Instance<Bar>
para encontrar la que desea.
Me han dicho que debe destruir la Instance<Bar>
como lo he hecho anteriormente, y puedo verificar por experiencia que el código anterior funciona; Sin embargo, no puedo jurar que necesitas destruirlo.
Los puntos de inyección se procesan para un bean cuando se crea una instancia del contenedor, lo que limita el número de casos de uso para la inyección a nivel de método. La versión actual de la especificación reconoce los siguientes tipos de inyección de métodos:
Inyección del método inicializador
public class MyBean {
private Processor processor;
@Inject
public void setProcessor(final Processor processor) {
this.processor = processor;
}
}
Cuando se inyecta una instancia de MyBean
, la instancia del procesador también se inyectará, a través de su método de establecimiento.
Métodos de observación de eventos
public class MyEventHandler {
public void processSomeEvent(@Observes final SomeEvent event) {
}
}
La instancia de evento se inyecta directamente en el método de manejo de eventos (aunque no con la anotación @Inject)
Métodos de producción
public class ProcessorFactory {
@Produces public Processor getProcessor(@Inject final Gateway gateway) {
// ...
}
}
Los parámetros a los métodos del productor se inyectan automáticamente.
Puede utilizar la API de BeanManager en su método para obtener referencias contextuales o, dependiendo de su objetivo final, podría inyectar un
Instance<Bar>
Fuera del método y utilizarlo en el método.
Si lo que REALMENTE desea no es algo como el parámetro del método (que debe proporcionar el llamante), sino una instancia correctamente iniciada de un bean CDI cada vez que se llama al método, y se construye e inyecta completamente, luego verifique
javax.inject.Provider<T>
Básicamente, primero inyecte un proveedor a la clase.
@Inject Provider<YourBean> yourBeanProvider;
Luego, en el método, obtén una nueva instancia.
YourBean bean = yourBeanProvider.get();
Espero que esto ayude :)