Como usar anotações de tipo personalizado em Java

9

O Java 8 tem um recurso chamado Anotações de tipo ( JSR 308 ) . Eu gostaria de usá-lo para o simples mapeador de objetos para objetos. Gostaria de definir a anotação @ExpectedType como esta

@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExpectedType {
    public Class<?> value();
}

E, em seguida, use-o no meu código assim:

public class SomeServiceImpl() {
    public @ExpectedType(ObjectA_DTO.class) IObjectA doSomething(@ExpectedType(ObjectA_Entity.class) IObjectA obj) {
        return (ObjectA_Entity) obj; // it's correct
    }
}

IObjectA é uma interface implementada pelas classes ObjectA_DTO e ObjectA_Entity . O serviço que eu gostaria de usar desta maneira:

// it's correct
assert someService.doSomething(new ObjectA_DTO()).getClass() == ObjectA_DTO.class;

Gostaria de alterar a chamada dos métodos SomeServiceImpl para usar o mapeador de objetos. Poderia ser alcançado pelo código gerado usando JSR 269 ou por AOP.

O problema é que eu escrevi um processador de anotações simples e ele não lida com anotações de tipo. A fonte do processador de anotações simples se parece com isso:

@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SimpleAnnotationsProcessor extends AbstractProcessor {

    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Messager messager = processingEnv.getMessager();
        try {
            for (TypeElement e : annotations) {
                messager.printMessage(Diagnostic.Kind.NOTE, e.toString());
                for (Element elem : roundEnv.getElementsAnnotatedWith(e)) {
                    messager.printMessage(Diagnostic.Kind.NOTE, elem.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

Alguma idéia de como usar ou como acessar anotações de tipo por SimpleAnnotationsProcessor? Uso de Pluggable Annotation Processing API não é necessário para mim eu acho que teria melhor desempenho do que a reflexão Java. De qualquer forma eu não sei como acessar a anotação de tipo via Java Reflection também.

    
por Boris Šuška 22.12.2014 в 17:40
fonte

3 respostas

3

Não sei se entendi o que você tenta alcançar, mas aqui está um exemplo de como você pode acessar suas anotações com a API de reflexão Java:

package test;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;

public class TypeParameterTest {

    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExpectedType {
        public Class<?> value();
    }

    public static interface IObjectA {}

    public static class ObjectA_DTO implements IObjectA {}

    public static class ObjectA_Entity implements IObjectA {}

    public static class SomeServiceImpl {
        public @ExpectedType(ObjectA_DTO.class) IObjectA doSomething(@ExpectedType(ObjectA_Entity.class) IObjectA obj) {
            return (ObjectA_Entity) obj;
        }
    }

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        Method m = SomeServiceImpl.class.getMethod("doSomething", IObjectA.class);
        AnnotatedType returnType = m.getAnnotatedReturnType();
        Annotation returnTypeAnnotation = returnType.getAnnotation(ExpectedType.class);
        System.out.println(returnTypeAnnotation);

        AnnotatedType[] parameters = m.getAnnotatedParameterTypes();
        for (AnnotatedType p : parameters) {
            Annotation parameterAnnotation = p.getAnnotation(ExpectedType.class);
            System.out.println(parameterAnnotation);
        }
    }
}

A saída é assim:

@test.TypeParameterTest$ExpectedType(value=class test.TypeParameterTest$ObjectA_DTO)
@test.TypeParameterTest$ExpectedType(value=class test.TypeParameterTest$ObjectA_Entity)

Note, no entanto, que nem todas as anotações de tipo possíveis são acessíveis através da API de reflexão, mas você pode sempre lê-las a partir do código de byte, se necessário (veja minha resposta aqui ).

    
por Balder 05.01.2015 / 15:39
fonte
0

Eu acho que você está misturando o uso de anotações em tempo de execução versus o uso do mesmo no tempo de "compilação" por várias ferramentas. Processor interface é para uso em ferramentas (compilador, gerador javadoc), não em seu código de tempo de execução.

    
por Arkadiy 05.01.2015 / 15:47
fonte
0
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SearchDefinition {

    public String identifier() default "";

}

@SearchDefinition - pode ser usado em qualquer lugar

    
por Rohith K 05.01.2015 / 16:16
fonte