Injeção de Dependências com CDI

Quem desenvolve aplicações há algum tempo, certamente já criou aquela classe com uma infinidade de objetos sendo instanciados na unha, de forma verborrágica. Criação de métodos getInstance() então, nem se fala..rs. Pensando nos pobres desenvolvedores, alguma alma solidária resolveu criar a tal da injeção de dependências. Mas o que diabos é isso, Raphael? A grosso modo, injeção de dependências é uma magia negra onde as dependências de uma classe deixaram de ser definidas programaticamente e o container da aplicação bateu no peito e falou: deixa comigo que eu gerencio essa parada. Desta forma, o programador deixou de ter a responsabilidade de fazer verificações e instanciações, entre outras formas de controlar a criação dos objetos de uma classe.

Acredito que um dos grandes responsáveis por disseminar essa ideia de injeção de dependências foi a stack do Spring Framework. Pra se ter uma ideia de como o paranauê simplificou a vida de nós programadores, veja esse exemplo de como, comumente, se gerenciava uma dependência numa classe, e outro usando a injeção de dependências do Spring Framework.

E é claro que a moda pegou! Ao longo dos anos essa tecnologia evoluiu bastante, até que a Oracle simpatizou com a ideia e resolveu tornar a injeção de dependências uma especificação da plataforma Java Enterprise Edition, a JSR-299. Esta especificação também é conhecida como CDI – Context and Dependency Injection. O CDI veio pra abalar as estruturas do seu código Java, prometendo um processo de desenvolvimento mais produtivo, com baixo acoplamento da solução e um ciclo de vida bem gerenciado.

A injeção de dependência com o CDI ocorre nos famosos pontos de injeção, que são bem amplos na verdade, mas neste tutorial veremos somente três deles:

  • Injeção por atributos
  • Injeção por métodos setters
  • Injeção por construtores

A primeira coisa a saber sobre o CDI, é que você pode utilizá-lo de forma separada e independente da plataforma Java EE. Com isso, nos deparamos com dois possíveis cenários:

  • Se você utilizar a biblioteca do Java EE, seja feliz. Não é necessário maiores configurações para utilizar os recursos do CDI no seu projeto. Para isso, use a dependência abaixo.
  • Se você não dispõe de um container Java EE, é possível baixar a dependência isolada do CDI e integrá-la com um servlet conainer, por exemplo. Mas para isso, será necessário uma configuração a mais. Primeiro baixe a dependência do CDI conforme abaixo:
Agora diga para o seu servlet container que é você quem manda na parada e ele vai gerenciar dependências, sim. Para isso, crie um arquivo beans.xml no diretório src/main/resources/META-INF. Ah, se o caminho não existir no seu projeto, deixa de preguiça e cria essa estrutura, macho.
Pronto! Já estamos aptos a fazer a magia acontecer (olhos brilhando de emoção #sqn).

Agora que temos tudo preparado, é preciso conhecer duas anotações fundamentais para o uso do CDI: a javax.inject.Named e a javax.inject.Inject.

 javax.inject.Named

Essa anotação é responsável por definir que uma determinada classe será gerenciada pelo container, ou seja, se você esquecer de usar esse cara e chamar a injeção do recurso, vai dar ruim! Lembre-se disso. Essa anotação é criada da seguinte forma:

Veja que ela tem um atributo value, que por padrão é vazio. Esse cara serve pra dar nome aos bois, se você desejar. Toda classe gerenciada pelo container deve ter a declaração do @Named em sua assinatura. Vejamos o uso dessa abençoada:

Ou se quiser dar um nome qualquer pro recurso:

A partir deste momento, o container saberá que a classe PessoaService será gerenciada por ele. Agora vejamos como consumir esse recurso sem esforço algum.

javax.inject.Inject

Essa anotação é responsável por dizer para o container: Amigo, desce uma classe desse tipo aqui pra mim, por favor! Neste ponto, é muito importante garantir que o recurso chamado tem o chapéu do @Named, caso contrário, vai dar m***.

Segue a declaração dessa anotação ungida:

Lembra dos três pontos de injeção que falei lá em cima? Olha eles aí sendo declarados pela anotação @Target!!!!! Veremos a seguir exemplos de como usar a injeção da classe PessoaService nesses três pontos de injeção. Nossa classe de exemplo se chamará PessoaCaller, ok?

Injeção por atributo

Crie um atributo do tipo PessoaService na sua classe e simplesmente coloque um @Inject em cima ou ao lado dele e parta para o abraço!

Agora se você quis ser o diferentão e resolveu especificar o campo value quando mapeou o recurso, é necessário especificar o nome aqui também. Fica assim, ó:

Injeção por método

Essa forma de injeção geralmente acontece no método setter do atributo. Particularmente não sou muito de usar dessa forma, mas vamos lá. O método setter consiste em receber um argumento, geralmente, do mesmo tipo do atributo em questão e em seguida declaramos que o atributo será igual ao argumento do método. Pois bem, o ponto de injeção nesse caso ocorre na assinatura do método. Vejamos:

Se quis ser o diferentão de novo e especificou o value, é preciso mapear o recurso com o nome utilizado através do parâmetro do método. Se liga aí:

Injeção pelo construtor

Pra usar esse aqui o cara tem que ser o diferentão dos diferentões. Nunca vi um projeto usando dessa forma, maaaaas. Nesse caso é preciso criar um construtor personalizado e público, recebendo como parâmetro um objeto do mesmo tipo do recurso mapeado. O ponto de injeção ocorre na assinatura do construtor.

Se usou o atributo value, a regra que se aplica aqui é a mesma da injeção por método.

É isso aí, divirta-se!

Nota de edição: Assim como toda especificação Java, existem implementações referentes a cada uma delas. Com o CDI não é diferente, existem algumas no mercado, mas a JSR-299 é fundamentada na implementação do CDI Weld.

Written by Raphael Oliveira Neves
Engenheiro de software, evangelista de novas tecnologias e apaixonado por arquitetura e desenvolvimento de software utilizando Java.