|
Annotations
Por Arthur Silva Freire(arthur.freire@ccc.ufcg.edu.br)
Neste mês, a Coluna Java abordará um recurso que foi introduzido como padrão de linguagem na versão 1.5. Estamos falando de Annotations. Saiba o que é, pra que serve e como criar sua própria Annotation.
Você sabe o que são Annotations? Adivinha... são anotações. É um artifício que você tem para fazer alguma marcação em atributo, método, classe, entre outros. Dessa forma, podemos evitar, em muitos casos, arquivos XML de configuração, que tornam difícil a compreensão de alguns sistemas. Elas devem ser sempre declaradas antes do objeto que você quer anotar e uma @ (arroba) deve preceder o nome da sua anotação. Veja um exemplo simples abaixo .
@MinhaAnotacao
class MinhaClasse {
}
Nesta matéria, mostraremos dois exemplos para o uso de Annotations. Vamos ao primeiro.
Todos nós sabemos que uma fase importante no desenvolvimento de software é a de testes. Você pode definir que todos os métodos que tiverem a anotação “@Testar” serão testados. Vamos agora criar essa anotação.
Testar.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Testar { }
//Observem que a nossa anotação deve ser anotada com meta-anotações.
//A anotação @Retention(RetentionPolicy.RUNTIME) diz que a VM deve manter
//essas anotações em tempo de execução para que sejam lidas a partir da reflexão.
//Outras opções seriam: SOURCE e CLASS.
//E a anotação @Target(ElementType.METHOD) indica que a nossa anotação só é
//aplicada a métodos. Outras opções seriam: FIELD, TYPE (classe e interface),
//PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, e PACKAGE.
Pronto, criamos a nossa anotação. Agora, criaremos uma classe que será testada.
ClasseParaTestar.java
public class ClasseParaTestar {
//Como o propósito é só demonstrar as anotações, os métodos não fazem nada.
@Testar
public void metodo1() {
throw new RuntimeException("Deu zebra!");
}
@Testar
public void metodo2() {
}
@Testar
public void metodo3() {
}
public void metodo4() {
}
@Testar
public void metodo5() {
throw new RuntimeException("Ixi maria... Erro!");
}
public void metodo6() {
}
@Testar
public void metodo7() {
}
public void metodo8() {
}
}
Agora que nossos métodos já estão anotados, vamos criar a classe principal do nosso framework de testes.
Testador.java
public class Testador {
public static void testar(Object obj) {
Class> classe = obj.getClass();
int passou = 0;
int falhou = 0;
System.out.println("-------------Inicio dos Testes--------------");
for (Method m : classe.getDeclaredMethods()) {
if (m.isAnnotationPresent(Testar.class)) {
try {
System.out.print("Testando o método: "; + m.getName());
m.invoke(obj);
passou++;
System.out.println(" => passou!");
} catch (Throwable t) {
falhou++;
System.out.println(" => falhou! " + t.getCause());
}
}
}
System.out.println("---------------Fim dos Testes---------------");
System.out.println("Passaram: " + passou + ", Falharam: " + falhou);
}
}
Para rodar, basta chamar o método estático passando um objeto da classe que você deseja testar.
Testador.testar(new ClasseParaTestar());Esta será a saída para o primeiro exemplo: -------------Inicio dos Testes-------------- Testando o método: metodo1 =>; falhou! java.lang.RuntimeException: Deu zebra! Testando o método: metodo2 =>; passou! Testando o método: metodo3 =>; passou! Testando o método: metodo5 =>; falhou! java.lang.RuntimeException: Ixi maria... Erro! Testando o método: metodo7 =>; passou! ---------------Fim dos Testes--------------- Passaram: 3, Falharam: 2O nosso segundo exemplo consiste em criar uma anotação para validar os atributos. Vamos criar uma anotação para verificar se um atributo contém um determinado texto e outra para verificar se o atributo é positivo. ValidarPositivo.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ValidarPositivo { }
ValidarContemTexto.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ValidarContemTexto {
int min() default 1;
}
//As anotações podem conter atributos para realizar alguma lógica durante o processamento dessas.
//No nosso caso, a anotação @ValidarContemTexto irá validar se o atributo que está
//decorado com a anotação possui pelo menos min caracteres (que por default é 1).
//Reparem que a meta-anotação @Target é ElementType.FIELD, porque vamos utilizar essas anotações
//para decorar atributos.
A nossa classe de testes será a seguinte:
Usuario.java
public class Usuario {
@ValidarContemTexto(min = 10)
private String login;
@ValidarContemTexto(min = 20)
private String senha;
@ValidarPositivo
private int nivel;
//Construtores, getters e setters
//...
}
Agora, a classe responsável pela validação:
Validador.java
public class Validador {
public static boolean validar(Object obj) {
Class> classe = obj.getClass();
boolean ok = true;
for (Field f : classe.getDeclaredFields()) {
f.setAccessible(true);
//Annotation @ValidarPositivo
if (f.isAnnotationPresent(ValidarPositivo.class)) {
try {
int num = Integer.parseInt(f.get(obj).toString());
if (num <= 0) {
ok = false;
throw new Exception();
}
} catch (Throwable t) {
System.out.println(f.getName() + " deve ser um valor inteiro positivo.");
}
}
//Annotation @ValidarContemTexto
if (f.isAnnotationPresent(ValidarContemTexto.class)) {
ValidarContemTexto anotacao = f.getAnnotation(ValidarContemTexto.class);
try {
String texto = f.get(obj).toString();
if (texto.length() < anotacao.min()) {
ok = false;
System.out.println(f.getName() + " deve possuir pelo menos " + anotacao.min() + " caracteres.");
}
} catch (Throwable t) {
System.out.println(f.getName() + ": " + t.getCause());
}
}
}
return ok;
}
}
O código a seguir cria três usuários e executa a validação com cada um deles.
ArrayListO resultado é este: Validando usuario: login login deve possuir pelo menos 10 caracteres. senha deve possuir pelo menos 20 caracteres. Corrija os erros. Validando usuario: arthur senha deve possuir pelo menos 20 caracteres. nivel deve ser um valor inteiro positivo. Corrija os erros. Validando usuario: juca Usuário OK.Isso é o que tínhamos pra mostrar nesta matéria, uma breve introdução a Annotations. Caso queira se aprofundar mais, acesse o link da documentação. Jornal PETNews - Edição: Jeymisson Oliveira - Revisão: Iago Araújo e Joseana Fechine
Grupo PET Computação UFCG, 2012. All rights reserved. |
|