java annotation-processing

java - ¿Cómo puedo referirme a las implementaciones de un método en el procesamiento de anotaciones?



annotation-processing (4)

Estoy jugando con el procesamiento de anotaciones Java (javax).

Supongamos que tengo una anotación para los métodos:

@Target(ElementType.METHOD) public @interface MethodAnnotation { }

Ahora quiero procesar todos los métodos que se anulan de un tipo con el método anotado:

interface MyInterface() { @MethodAnnotation void f() } class MyClass implements MyInterface { override void f() { } // <- I want to process this method }

@Inherited meta-anotación @Inherited no parece ser adecuada aquí:

Tenga en cuenta que este tipo de meta-anotación no tiene ningún efecto si el tipo anotado se utiliza para anotar algo que no sea una clase.

Además, ¿es posible procesar un método de clase heredado que no se invalida en una subclase? Me gusta esto:

class MyClass { @MethodAnnotation void f() { } } class MySubClass extends MyClass { } // <- I want to process its f() // or at least to find out that it doesn''t // override the method

¿Cómo puedo acceder a los métodos anulados de un método determinado dentro de AbstractProcessor ?

Supongo que, para lograrlo, necesito encontrar subclases de la clase de eclosión, pero tampoco he encontrado la manera de hacerlo.

UPD : Supongo que es posible usar RoundEnvironment.getRootElements() pero todavía no se encuentra una forma adecuada de hacerlo.


La respuesta corta es que el procesamiento de anotaciones fuera de la caja no lo hará fácil para usted, pero puede hacerse.

En lugar de utilizar el mecanismo de envío normal para el procesamiento, en realidad tendrá que procesar todos los métodos y realizar el filtrado usted mismo.

Paso 1:

Defina su procesador para que admita todas las anotaciones utilizando "*" como su tipo de anotación compatible. Esto significará que su procesador será invocado en cada ronda.

Paso 2:

Use getRootElements para obtener el conjunto completo de elementos en cada ronda.

Paso 3:

Cree un ElementScanner8 para atravesar cualquier elemento que encuentre para buscar ExecutableElement s. Si está dispuesto a confiar en que los métodos anulados están anotados con @Override , puede hacer un filtro rápido sobre ellos. De lo contrario, basta con mirar a todos ellos.

Etapa 4:

Ahora debe ver si el método anula un método con la anotación que está buscando. No hay una manera fácil de obtener métodos que un método dado haya invalidado, por lo que necesita obtener el elemento de encierro del método, ver su superclass e implementar interfaces (recursivamente), obtener sus elementos encerrados , filtrar los métodos y probarlos. ver si ha sido anulado por el método en cuestión. Si es así, puede revisar las annotations para ver si tiene alguna que le importe.

Paso 5:

En este punto, debe tener el método de anulación, el método anulado y el espejo de anotación que estaba buscando, por lo que debería poder implementar la lógica que desee.


Las anotaciones de los métodos no se heredan. Las anotaciones de tipo se pueden heredar mediante el uso de la anotación "@Inherited".

Lo que podría hacer es definir una interfaz funcional con una anotación de tipo heredada, sin embargo, no sé si esto es lo suficientemente elegante para usted.


Si esas anotaciones están disponibles en tiempo de ejecución, y desea llegar a ellas en tiempo de ejecución, puede usar la biblioteca de Reflections .

Por ejemplo:

Collection<URL> urls = ClasspathHelper.forPackage("nl.shopname.location.domain"); Reflections reflections = new Reflections( new ConfigurationBuilder().setUrls(urls).setScanners(new FieldAnnotationsScanner())); Set<Field> fieldsWithAnnotation = reflections.getFieldsAnnotatedWith(MyAnnotation.class);


de acuerdo con el javadoc de javax.annotation.processing.Processor en Jsr269-1.8

Una anotación está presente si cumple con la definición de estar presente en AnnotatedConstruct. En resumen, una anotación se considera presente a los fines del descubrimiento si está directamente presente o presente a través de la herencia. Una anotación no se considera presente en virtud de estar envuelta por una anotación de contenedor ...

El JavaDoc de AnnotatedConstruct#getAnnotationsByType dice que devuelve anotaciones presentes de forma indirecta, por lo que creo que debería buscar métodos y verificar si tienen la anotación indirectamente utilizando esta llamada. Algo en el espíritu de this .

Descargo de responsabilidad ... no lo he probado;)