25%Off

Compre com desconto

Começou!

Começou!

00

DIAS

00

HORAS

00

MIN

00

SEG

Use CDI no seu próximo projeto Java

Use CDI no seu próximo projeto Java
slopes
slopes

Compartilhe

CDI é a especificação do Java EE 6 que cuida da parte de injeção de dependências. E, além de ser oficial e estar incluída em todos os servidores de aplicação, é tão boa e produtiva que já tem gente questionando o papel do Spring nos dias de hoje.

O CDI se encaixa muito bem em todo tipo de projeto Java. Se você usa JSF2, usar CDI é natural, como mostramos no nosso curso FJ-26. Mas mesmo para aplicações Web simples, com apenas Servlets, o CDI é um grande ganho.

Habilitando CDI

Habilitar o CDI no projeto é muito simples. Se você já está usando um servidor Java EE 6, basta criar um arquivo vazio chamado beans.xml na pasta META-INF do seu projeto (ou WEB-INF num projeto web). Esse é um simples arquivo de marcação e apenas sua presença já faz com que o servidor habilite o suporte a CDI e escaneie suas classes automaticamente.

Se você estiver usando Tomcat, Jetty ou outro servidor antes do Java EE 6, ainda é possível habilitar o CDI copiando e configurando o JAR de alguma de suas implementações. Vamos usar o Weld, a implementação de referência e a mais usada (já embutida no JBoss e no Glassfish).

No caso do Tomcat, os passos de configuração são:

Feito isso, basta criar o tal arquivo META-INF/beans.xml vazio no projeto.

Banner da promoção da black friday, com os dizeres: A Black Friday Alura está chegando. Faça parte da Lista VIP, receba o maior desconto do ano em primeira mão e garanta bônus exclusivos. Quero ser VIP

Tudo são beans

Com o CDI habilitado, praticamente todas as classes do projeto são consideradas managed beans e, portanto, passíveis de injeção e de serem injetadas. Podemos usar com CDI toda classe pública com um construtor público padrão ou algum que receba parâmetros e esteja anotado com @Inject.

Aliás, essa anotação @Inject é a base de todo o CDI: é ela quem permite a injeção de dependências e devemos usá-la nos pontos que queremos injeção automática, sejam construtores, setters ou atributos privados.

Essa anotação, embora usada com CDI, faz parte na verdade de uma outra especificação, a JSR330. Essa é uma especificação bastante simples, com apenas algumas anotações relacionadas à injeção de dependências no pacote javax.inject. A ideia é ter um conjunto básico de recursos para injeção a serem suportados em todos os frameworks do tipo - além do CDI, Spring, Google Guice, PicoContainer e outros frameworks suportam essas anotações.

Primeira injeção

Imagine que temos uma classe ProdutoDAO que cuida de persistir objetos Produto:

 public class ProdutoDAO { public void adiciona(Produto produto) { // ... implementação } } 

Essa classe simples, sem nenhuma configuração particular, pode ter objetos injetados em qualquer outro ponto da aplicação. Basta usar a anotação @Inject:

 public class ProdutoController { @Inject private ProdutoDAO dao;

public String inserir() { Produto p = // ... dao.adiciona(p); return "Produto adicionado!"; } } 

Poderíamos também ter feito a própria classe ProdutoDAO receber um EntityManager da JPA para trabalhar com a persistência:

 public class ProdutoDAO { @Inject private EntityManager manager;

public void adiciona(Produto produto) { manager.persist(produto); } } 

Produção de objetos

Sempre que encontrar um ponto de injeção, o CDI vai tentar instanciar a classe sendo referenciada. No caso do DAO anterior, ao criá-lo, o CDI vai tentar dar new em EntityManager.

Mas EntityManager, assim como vários outros objetos, não pode ser criado tão facilmente assim. A criação de um EntityManager exige a chamada do método createEntityManager no EntityManagerFactory correspondente. É um objeto com um processo de fabricação particular.

Nos Design Patterns, sempre que encontramos esse tipo de cenário, criamos uma Factory para aquele objeto. É um simples método que encapsula a criação não-trivial do objeto em questão. Com CDI é a mesma coisa.

Vamos criar um método em uma classe qualquer do sistema que cuide da produção de objetos EntityManager. E podemos indicar ao CDI que queremos que ele use esse método sempre que alguém pedir a injeção de um EntityManager. Fazemos isso com a anotação @Produces:

 public class ProdutorEntityManager { private static EntityManagerFactory factory = Persistence.createEntiyManagerFactory("default");

@Produces public EntityManager criaEntityManager() { return factory.createEntityManager(); } } 

Agora, todos os pontos de injeção que precisarem de EntityManager irão invocar essa fábrica anotada com @Produces.

Escopos

Mas quantos EntityManagers vamos criar com o código acima? Por padrão, toda dependência no CDI possui um escopo chamado Dependant. Isso é: será instanciada tantas vezes quanto quem estiver chamando for. Certamente não é o que queremos com nosso EntityManager.

É usual criar um EntityManager por requisição em uma aplicação Web. Podemos indicar isso apenas anotando o método produtor com @RequestScoped:

 public class ProdutorEntityManager {

@Produces @RequestScoped public EntityManager criaEntityManager() { // ... } } 

Agora, um novo EntityManager será criado associado a um request. Se mais de uma classe pedir um EntityManager durante o mesmo request, a mesma instância será passada, evitando desperdício de recursos. Outros escopos comuns são @SessionScoped e @ApplicationScoped.

Mais: como definimos o escopo da dependência, temos agora uma visão clara de seu ciclo de vida. O objeto durará apenas um request, e será descartado quando o request acabar.

O CDI nos deixa, inclusive, executar algo na fase de descarte da dependência, ao final da requsição. No nossa caso, será muito útil para chamar o close no EntityManager. Basta criar um método que receba a dependência a ser descartada e anotar o parâmetro com @Disposes:

 public class ProdutorEntityManager {

@Produces @RequestScoped public EntityManager criaEntityManager() { // ... }

public void finaliza(@Disposes EntityManager manager) { manager.close(); } } 

O método finaliza será chamado automaticamente pelo CDI ao final do request e fará o fechamento do EntityManager.

Use CDI no seu próximo projeto

O CDI é extremamente completo e poderoso. Esse artigo mostrou apenas o básico e o início do trabalho. Mas seu container de injeção typesafe com anotações simples e produtivas tem muitos outros recursos. Mostrei várias funcionalidades do CDI em uma palestra no JavaOne Brasil que você pode acompanhar a seguir:

Aqui mesmo no blog já mostramos como fazer a produção de dependências de tipos genéricos. Além disso, há recursos como qualifiers, interceptadores, decorators, eventos e muito mais. Mostramos várias dessas funcionalidades no curso FJ-26 da Caelum, inclusive com o JBoss Seam 3, uma ótima companhia para o CDI.

E você, o que acha do CDI? Tem usado em seus projetos?

Veja outros artigos sobre Inovação & Gestão