Java CDI — Um tutorial
Fiz um tutorial mais recente no dev.to/vepo.
Java CDI é um padrão de software, incorporado desde o Java EE 6, para lidar com Injeção de Contexto e Dependência. A especificação é uma das implementações da técnica Inversão de Controle (Inversion of Control).
Sumário
- Configurando, Injetando dependências e Interceptando métodos
- Usando Qualifiers e chamando programaticamente
Configurando o projeto
Para que as dependências sejam encontradas pelo Container CDI, é preciso que exista o arquivo beans.xml
na pasta META-INF
.
Em um projeto maven, esse arquivo ficaria em src/main/resources/META-INF/beans.xml
.
Injetando Dependências
Para injetar uma dependência em qualquer lugar do código, basta se usar a anotação @Inject
.
No código acima, o campo myManager
será inicializado automaticamente desde que a classe tenha um construtor publico sem parâmetros.
Provendo Dependências
Para que as dependências possam ser injetadas, é preciso que algum trecho de código seja chamado. No código abaixo definimos a classe MyManager.java
.
A inicialização e a finalização desse objeto será responsabilidade do Container. Observer que a anotação @ApplicationScoped
define o comportamento desses objetos, nesse caso só existirá uma instância que é iniciada juntamente com o container. Para ver os outros escopos existentes:
Provendo Dependências — Factories
Caso a dependência seja uma inplementação externa, é possível criar uma Factory para a dependência.
Usando uma Factory, é necessário muito cuidado para ver se não há Memory Leak, pois o Container CDI irá chamar o metodo com @Produces
várias vezes.
Enviando e Recebendo events
Para criar uma aplicação com alta coesão e baixo acoplamento, muitas vezes não é necessário que uma funcionalidade chame a outra. Quando uma compra é finalizada, a nota fiscal pode ser emitida sem que o código de finalização chame o código de emissão. Isso pode ser feito usando eventos.
Usando o Java CDI, para se emitir um evento, basta injetar uma instância da class javax.enterprise.event.Event
e disparar o evento.
Na outra ponta, rodando dentro da mesma JVM, deve estar o código que processa esse evento usando a anotação @Observe
:
Interceptando Métodos
Uma outra possibilidade com CDI é criar interceptors, isso pode ser muito útil para se construir aplicações usando Programação Orientada a Aspecto. A mágica nesse caso não aparece tão fácil.
Primeiro crie uma Annotation descrevendo o que deseja ser feito:
O próximo passo é implementar o que deve ser feito durante a execução, para isso crie o Interceptor:
No caso acima, estou apenas logando a execução, mas poderia ser um controle transacional, ou uma auditoria.
Para que o container CDI saiba da existência desse Interceptor, é necessário adicionar ele ao beans.xml
.
Pronto! Agora funcionará!
Criando o Container
O container CDI já é inicializado em muitos projetos Jakarta EE, antigo Java EE. Como exemplo veja o código gerado pelo Thorntail.io.
Criando o Container em aplicações Java SE
Não é preciso que seja um container Web com Jakarta EE para rodar aplicações CDI. Dá para se configurar o container para pequenos projetos, que são bastante úteis como microserviços de backend, por exemplo, processar eventos Kafka.
Para isso adicione como dependência o Weld, e inicialize o container manualmente.
Conclusão
Java CDI é um padrão que pode lhe ajudar a criar aplicações mais organizadas reduzindo o acoplamento. Também é possível criar soluções aparentemente mágicas, mas que na verdade são gerenciadas por um código robusto e bem testado!
Continuação
Código fonte
O exemplo desse tutorial pode ser encontrado no meu github: