Por que eu devo ler este artigo:Quando se fala em CDI, na maioria das vezes são enfatizados apenas os aspectos relacionados à injeção de dependências, visto que essa especificação utiliza o termo dependency injection em seu nome. Entretanto, CDI está repleta de recursos e vai muito além da injeção de dependências, podendo facilitar e muito a implementação dos mais variados requisitos de um software. Os recursos Interceptors e Decorators, por exemplo, temas deste artigo, são muito úteis e importantes na criação de soluções robustas e aderentes às práticas mais modernas de arquitetura de software ao proporcionar mecanismos para extensão da funcionalidade da aplicação sem alterações bruscas no código fonte, tornando o desenvolvimento mais rápido e confiável.

CDI é a especificação do Java EE para lidar com contextos (diferentes estados da aplicação e seus objetos relacionados) e injeção de dependências. Essa especificação se integra tão bem e de forma tão natural ao restante da plataforma Java que, muitas vezes, seus recursos são utilizados mesmo quando o desenvolvedor não conhece os detalhes da especificação.

Quando o assunto é CDI, para aqueles que conhecem apenas o básico da especificação, o primeiro assunto que vem à cabeça são os recursos relacionados à injeção de dependências, como: a injeção de dependência em si, por meio da anotação @Inject; a produção de beans, por meio da anotação @Produces; e a definição de escopo dos beans por meio da anotação @SessionScoped. CDI, no entanto, oferece muitos outros recursos que podem melhorar ainda mais a arquitetura da aplicação, tanto em termos de acoplamento, quanto em termos de coesão e granularidade, de forma a evitar que o código se torne complexo e custoso de se manter.

Entre os recursos que muitas vezes passam despercebidos pela maioria dos desenvolvedores estão os interceptors e os decorators. Com base nisso, nos próximos tópicos analisaremos esses recursos através de diferentes cenários nos quais eles são indicados.

Interceptors

Interceptors, ou interceptadores, em CDI, são filtros que permitem executar operações antes ou depois das chamadas a métodos e que podem, inclusive, substituir a chamada ao método original. Os interceptadores se baseiam em anotações, métodos e classes para definir ou não a sua execução, e são úteis em muitos cenários, como incluir um cabeçalho padrão em todas as respostas HTTP. Esse mecanismo simplifica a implementação de pequenos trechos de código em diferentes pontos da aplicação com o mínimo de alterações.

Como será possível notar a partir de agora, existem vários tipos de interceptadores, entre eles: @AroundInvoke, que intercepta métodos determinados pelo desenvolvedor por meio de anotações; @AroundTimeout, que intercepta métodos invocados pelo serviço de timer do Java EE (veja a seção Links para saber mais sobre o serviço de timer); e interceptadores de ciclo de vida, que interceptam a construção e destruição de beans, como o @AroundTimeout.

Nota: Além dos Interceptors da CDI, também existem os Interceptors da API de Servlets. Ambos seguem o mesmo conceito, entretanto, os Interceptors da CDI interceptam chamadas a métodos, enquanto os Interceptors da API de Servlets interceptam requisições HTTP.

A Figura 1 ilustra o funcionamento de alguns interceptadores em uma invocação a um método. Quando se habilita a CDI no projeto, a chamada a qualquer método sempre será executada em um contexto CDI. Dessa forma, caso o método invocado ou a classe na qual ele foi implementado sejam anotados com um interceptador, esse interceptador será disparado, encapsulando e gerenciando a invocação do método. Esse mecanismo é excelente para definir requisitos transversais, como a implementação de logs ou de segurança em toda a aplicação. Para saber mais sobre requisitos transversais, veja o BOX 1.

BOX 1. Requisitos transversais
Requisito transversal é um termo que vem, pouco a pouco, substituindo o termo requisito não funcional. Um requisito transversal representa comportamentos transversais do sistema, ou seja, comportamentos que deveriam ser implementados em todos os módulos, definindo restrições, atributos de qualidade e/ou a forma de operação.

Exemplos de requisitos transversais incluem segurança, desempenho e escalabilidade. Eles dizem respeito a toda a aplicação, por exemplo: não faz sentido definir um controle de acesso por meio de uma tela de login sem um mecanismo que controle o acesso a todas as telas do sistema, ou ainda definir requisitos de escalabilidade ou desempenho sem considerar a aplicação como um todo.

Tendo em vista a importância dos requisitos transversais, muitas abordagens surgiram para melhorar a implementação dos mesmos pela aplicação. O esforço mais conhecido nessa área é a programação orientada a aspectos, implementada por frameworks como AspectJ e Spring AOP, que, inclusive, foram grandes responsáveis pela popularização do termo requisitos transversais. Além disso, mecanismos como os Interceptors na API de Servlet e na CDI ofer ...

Quer ler esse conteúdo completo? Tenha acesso completo