Java Annotations na prática

View Code

As anotações são um recurso disponível desde a versão 5 do Java. Tratam-se de  metadados que não fazem parte do próprio programa e não tem efeito direto na sua execução. Mas então para quê elas são úteis? Podemos manipula-las em tempo de execução. Veremos como tirar vantagem disso numa situação problema.

Anotações podem ser manipuladas em tempo de execução

O Problema

Imagine a situação onde temos uma entidade chamada Customer  e que precisamos registrar o histórico de alterações de determinados campos dessa tabela. Apenas os campos phone e address  precisam ter o histórico. Precisaremos saber qual o campo alterado, o seu valor antigo e o seu novo valor.

A Solução

A nossa receita de solução envolve dois ingredientes importantes: anotações e a API Reflection do Java. Essa dupla dinâmica atuará da seguinte maneira: As anotações indicarão quais campos precisam ter o histórico registrado e a API Reflection nos permitirá verificar em tempo de execução a presença ou não dessas anotações nos campos. Mãos ao código!

Criando a anotação

Vamos começar definindo nossa própria anotação. Vamos chama-la de Auditable .

Olha que interessante, utilizamos anotações para definir a nossa anotação. A anotação Target indica qual elemento do programa a nossa anotação pode ser aplicada. No nosso caso a anotação Auditable  será aplicada em campos de classe. A anotação Retention recebendo o parâmetro  RetentionPolicy.RUNTIME  indica que ela estará disponível para ser acessada em tempo de execução que é o que vamos precisar.

Aplicando a anotação na classe

Com a nossa anotação criada é hora de utiliza-la. Como definimos ela será aplicada em campos da classe. Como queremos que apenas os campos address  e phone  armazenem seu histórico, colocamos a annotation somente para esses campos.

 

Usando a API Reflection

A API Reflection nos oferece o método isAnnotationPresent . O trecho de código abaixo é auto-explicativo: a instrução retorna verdadeiro se o campo phone  é anotado com a anotação Auditable

Juntando tudo

No nosso método de update vamos utilizar a API Reflection do Java para verificar se os campos alterados possuem precisam armazenar o histórico de alterações.

(#1) Armazeno uma lista de Map  contendo o nome do campo, o valor antigo e o valor novo

(#2) Tirando vantagem do açúcar sintático do Groovy, nós removemos da lista todos os campos que não possuem a anotação.

(#3) Iteramos todos os campos e salvamos o histórico deles na base

Concluindo

Uma outra solução seria ao salvar um novo registro na nossa tabela Customer  verificar se o campo alterado precisa ser registrado no histórico. Isso geraria uma implementação com estruturas condicionais que deixariam o código verboso.

As anotações podem nos ajudar a construir soluções elegantes para os nossos problemas do dia-a-dia. Elas também podem ser utilizadas pelo compilador para detectar erros ou por ferramentas para geração de código ou estruturas XML. O Java já possui anotações pré-definidas como o @Test  do JUnit, o @Override , o @SuppresWarnings . Frameworks consolidados no desenvolvimento Java como Hibernate e Spring utilizam poderosamente das annotations. Lembra da  @Entity do Hibernate?

Referências

  1. https://docs.oracle.com/javase/tutorial/java/annotations/basics.html
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/Target.html
  3. http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/reflection-e-annotations/#9-5-usando-bem-anotacoes