A lógica de negócio de uma aplicação nem sempre é independente, muitas vezes nossa implementação depende de outros recursos que estão no servidor de aplicação como JDBC, JMS, Session Bean e Entity Manager.

Para gerenciar essas dependências, os componentes Java EE oferecem referências para recursos que estão definidos em meta-dados externos ou anotações. Essas referências nada mais são do que um link nomeado para os recursos que pode ser determinado dinamicamente em tempo de execução dentro do código da aplicação ou automaticamente pelo container quando a instância do componente é criada.

Toda referência tem um nome e um destino. O nome é usado pelo código da aplicação para determinar a referência dinamicamente. O servidor usa a informação de destino para encontrar o recurso que a aplicação está procurando.

1. Injeção de Dependência

Quando uma anotação de recurso é colocada em um campo ou um método setter, o nome para aquele recurso será ligado ao ambiente de contexto nomeado quando o componente é criado e por fim o servidor faz a procura automaticamente e seta o resultado dentro da classe instanciada.

O processo de automaticamente procurar um recurso e setar ele dentro de uma classe é chamado de injeção de dependência porque o servidor é chamado para injetar a dependência resolvida dentro da classe.

Esta técnica, uma de várias referidas como inversão de controle, remove a chatice de termos que manualmente procurar o recurso através do contexto de ambiente JNDI.

Injeção de dependência é considerada uma melhor prática para desenvolvimento de aplicações, não apenas porque ela reduz a necessidades de procuras por JNDI, mas também porque ela simplifica os testes. Sem qualquer código para a API JNDI na classe que tem dependências no servidor de aplicação, a classe do bean pode ser instanciado diretamente no teste de unidade. O desenvolvedor pode então manualmente prover as dependências requeridas e testar a funcionalidade da classe em questão ao invés de se preocupar em como trabalhar com a API JNDI.

1.1. Injeção nos Campos

A primeira forma de injeção de dependência é chamada injeção de campo ou em inglês field injection. Injetando uma dependência dentro de um campo significa que depois que o servidor procura a dependência no ambiente de contexto nomeado, o resultado é colocado diretamente dentro do campo anotado da classe.

No exemplo abaixo temos a anotação EJB onde se injeta o resultado no campo auditoria.

Listagem 1: Usando Injeção de Dependência em Campo

@Stateless
public class DepositoServiceBean implements DepositoService {
@EJB AuditoriaService auditoria;
	// ...
}

A Injeção de dependência em campos é certamente a mais fácil de ser implementada, no entanto, se você está planejando um teste de unidade para a sua classe considere o escopo de pacote para injeção em campo se você quer um teste de unidade sem ter de adicionar um setter.

1.2. Injeção nos Métodos Setter

A segunda forma de injeção de dependência é chamada de injeção de dependência em métodos setter e envolve anotar um método setter ao invés de um campo de uma classe. Quando o servidor resolve esta referência, ele invocará o método setter anotado com o resultado da procura (lookup). Abaixo temos um exemplo de injeção de dependência usando um setter.

Listagem 2: Usando injeção em métodos setter.

@Stateless
public class DepositoServiceBean implements DepositoService {
	private AuditoriaService auditoria;

	@EJB
	public void setAuditoriaService(AuditoriaService auditoria) {
		this.auditoria = auditoria;
	}

	// ...

}

Este estilo de injeção permite que campos privados também trabalhem com testes de unidade. Cada teste pode simplesmente instanciar a classe do bean e manualmente executar a injeção de dependência invocando o método setter, frequentemente provendo uma implementação do recurso requerido que é adaptado para o teste.

1.3. Declarando Dependências

Abaixo descreveremos algumas das anotações de recursos definidas pelas especificações Java EE e EJB. Cada anotação tem um atributo "name" para opcionalmente especificarmos o nome da referência para uma dependência. Outros atributos nas anotações são especificas dependendo do tipo de recurso que necessita para ser adquirida.

1.3.1. Referenciando um Contexto de Persistência

No ambiente Java EE, a anotação @PersistenceContext pode ser usada para declarar uma dependência em um Contexto de Persistência e ter um Entity Manager para aquele contexto de persistência adquirido automaticamente.

Segue abaixo um exemplo usando a anotação @PersistenceContext para adquirir um Entity Manager através da injeção de dependência. O elemento unitName especifica o nome da unidade de persistência na qual o contexto de persistência será baseado.

Listagem 3: Injetando um EntityManager.

@Stateless
public class EmpregadoServiceBean implements EmpregadoService {
	@PersistenceContext(unitName="EmpregadoService")
	EntityManager em;
	
	// ...

}

1.3.2. Referenciando uma Unidade de Persistência

O EntityManagerFactory para unidade de persistência pode ser referenciado usando a anotação @PersistenceUnit. Assim como a anotação @PersistenceContext, o elemento unitName identifica a unidade de persistência para a instância EntityManagerFactory que nós queremos acessar. Se o nome da unidade de persistência não esta especificada na anotação, o nome é determinado pelo provedor do serviço.

O exemplo abaixo demonstra a injeção de uma instância EntityManagerFactory num bean com estado de sessão. O bean, portanto cria uma instância EntityManager da fábrica durante o ciclo de vida PosConstruct.

Listagem 4: Injetando uma instância EntityManagerFactory.

@Stateful
public class EmpregadoServiceBean implements EmpregadoService {

	@PersistenceUnit(unitName="EmpregadoService")
	private EntityManagerFactory emf;

	private EntityManager em;

	@PostConstruct
	public void init() {
		em = emf.createEntityManager();
	}

	// ...

}

O EntityManagerFactory para a unidade de persistência não é frequentemente usada no ambiente Java EE porque Entity Managers injetados são mais fáceis de adquirir e usar. Existem diferenças importantes entre Entity Managers retornados por uma fábrica e providos por um servidor em resposta a uma anotação @PersistenceContext.

1.3.3. Referenciando um Enterprise JavaBeans

Quando um componente necessita acessar um EJB, ele declara uma referencia para um bean com a anotação @EJB. O destino deste tipo de referência é tipicamente um bean de sessão, isto ocorre porque beans Message-driven não tem interface de cliente, portanto eles não podem ser diretamente acessados e não podem ser injetados. O servidor procurará por todos os beans de sessão publicados (deployed) para encontrar um que implementa a interface de negócio requisitada.

Nos casos raros que dois beans de sessão implementam a mesma interface de negócio ou se o cliente necessita acessar um bean de sessão localizado em um jar diferente, então o elemento beanName pode também ser especificado para identificar o bean de sessão pelo seu nome.

Segue abaixo um exemplo utilizando a anotação EJB.

Listagem 5: Exemplo utilizando uma anotação EJB.

@Stateless
public class DepositoServiceBean implements DepositoService {
	@EJB(beanName="AuditoriaServiceBean")
	AuditoriaService auditoria;

	// ...

}

1.3.4. Referenciando Recursos de Servidor

A anotação @Resource é utilizada para todos os tipos de recursos que não correspondem a um dos tipos descritos anteriormente. Ele é utilizado para fábrica de recursos, mensagens, data sources, e outros recursos de servidor. A anotação @Resource é também a mais simples de definir, porque seu único elemento é o resourceType, na qual se permite que você especifique o tipo dos recursos se o servidor não pode encontrá-lo automaticamente.

Conclusão

Neste artigo vimos que o que é injeção de dependência e como podemos injetar dependências através de algumas anotações largamente utilizadas nas aplicações corporativas desenvolvidas em Java.

Referências