Último minuto

Implementando Contextos Java e Inyección de Dependencia (CDI)

La inyección de dependencia es una técnica popular en el desarrollo de aplicaciones empresariales java. En una inyección de dependencia, también llamada Inversión de Control (Inversion of Control - IoC), un componente especifica los recursos de los que depende.

Un inyector, típicamente un contenedor, proporciona los recursos al componente. Aunque la inyección de dependencia puede ser implementado de varias maneras, muchos desarrolladores lo implementan con anotaciones.

Nota: Traducción al español no autorizada del libro Java EE 6 Cookbook for Security, Tuning, and Extending Enterprise Applications - Capítulo "Implementing Java Contexts and Dependency Injection (CDI)"

El concepto de CDI tiene su origen el año 2002 con Rod Johnson (@springrod), quien lanzó el framework con la publicación de su libro Expert One-on-One J2EE and Development. Desde entonces, SpringFramework ha sido el framework más usado ampliamente en el mundo Java. La Inyección de Dependencia es usado en gran medida en frameworks de desarrollo Java tales como Spring  y Guice. Desafortunadamente,  no existe un enfoque estándar para la inyección de dependencia basada en anotaciones. En particular, un framework tal como Spring adopta un enfoque diferente para inyección de dependencia basada en anotaciones, que la de Guice.

Estos servicios hacen que los componentes Java EE, incluyendo EJB Session Beans y JavaServer Faces (JSF) managed beans, estén sujetos a contextos de ciclos de vida, para ser inyectados y para interactuar en una manera imprecisa para enlazarse a eventos. CDI unifica y simplifica los modelos de programación EJB y JSF y proporciona beans empresariales (enteprise beans) para reemplazar los beans  manejados (managed beans) en una aplicación JSF.

JSR 299 puede ser dividido en estos principales paquetes:
  • Alcances y contextos (Scopes and contexts) javax.context
  • Servicios de inyección de dependencias: javax.inject
  • Framework de integración SPI: javax.inject.manager
  • Servicio de notificación de eventos: javax.event
JSR 299 se basa fuertemente en anotaciones Java para las especificacón Context and Dependency Injection, JSR 330. JSR 330 contiene un conjunto de anotaciones para usarse en clases inyectables. Las anotaciones son las siguientes:
  • @Qualifier: Identifica anotaciones de cualificador. Los cualificadores son claves basados en tipos que ayudan a distinguir diferentes usos de objetos del mismo tipo.
  • @Inject: Identifica constructores, métodos y campos inyectables.
  • @Named: Es un calificador basado en cadena (String)
  • @Scope: Identifica anotaciones de alcance
  • @Singleton: Identifica un tipo que el inyector instancia solo una vez.

@Qualifier

La anotación @Qualifier del JSR 330 identifica y especifica la implementación de una clase Java o una interfaz a ser inyectada.
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface InjectableType {...}

@Inject

La anotación @Inject identifica un punto el cual una dependencia en una clase o interfaz Java puede ser inyectada en una clase destino. Esta inyección no solo crea una instancia, o prototipa un objeto por omisión, también puede inyectar un objeto singleton como tal:
@Stateful
@SessionScoped
@Model
public class ServiceWithInjectedType {
@Inject InjectableType injectable;
...
El contenedor buscará el tipo inyectable especificado por @Qualifier y automáticamente inyectará la referencia.

@Named

La anotación @Named proporciona los calificadores basados en cadenas en lugar de los basados en tipo. Un ejemplo de esto es:

http://download.oracle.com/javaee/6/api/javax/inject/Named.html
 
@Named
public class NamedBusinessType
implements InjectableType {...}

@Scope

Dentro de una aplicación web, un bean tiene que ser capaz de mantener el estado de la duración de la interacción del cliente con la aplicación. La siguiente tabla detalla los alcances de los beans.
AlcanceAnotaciónDuración
Requerimiento@RequestScopedLa interacción del cliente por un simple requerimiento HTTP
Sesión@SessionScopedLa interacción del cliente a través de varios requerimientos HTTP
Aplicación@ApplicationScopedComparte el estado a través de todas las interacciones de los clientes
Dependiente@DependentAlcance por omisión. Significa un objeto existe para servir exactamente a un cliente (bean), y tiene el mismo ciclo de vida del cliente (bean)
Conversación@ConversationScopedLa interacción del cliente con la aplicación JSF dentro de los dominios del controlador que se extiende a través de múltiples invocaciones del ciclo de vida del JSF
Las anotaciones de alcance basadas en clase se verían así:
@Stateful
@SessionScoped
@Model
public class ServiceWithInjectedType {
@Inject InjectableType injectableType;

Podemos también ,crear nuestros propios manejadores de alcance usando la anotación @Scope
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RUNTIME)
@javax.inject.Scope
public @interface CustomScoped {}