Как я могу ссылаться на реализации метода в обработке аннотаций?
Я играю с обработкой аннотации Java (javax).
Предположим, что у меня есть аннотация для методов:
@Target(ElementType.METHOD)
public @interface MethodAnnotation { }
Теперь я хочу обработать все методы, которые переопределены с типом с помощью аннотированного метода:
interface MyInterface() {
@MethodAnnotation
void f()
}
class MyClass implements MyInterface {
override void f() { } // <- I want to process this method
}
@Inherited
мета-аннотация, кажется, не подходит здесь:
Обратите внимание, что этот тип мета-аннотации не действует, если аннотированный тип используется для комментирования чего-либо другого, кроме класса.
Кроме того, возможно ли обработать метод унаследованного класса, который не переопределяется в подклассе? Вот так:
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
Как я могу получить доступ к переопределенным методам определенного метода в AbstractProcessor
?
Я думаю, для этого мне нужно найти подклассы класса eclosing, но я тоже не нашел способ сделать это.
UPD. Я полагаю, что это возможно, используя RoundEnvironment.getRootElements()
, но не нашел подходящего способа сделать это.
Ответы
Ответ 1
Короткий ответ заключается в том, что готовая обработка аннотаций не облегчит вам задачу, но это можно сделать.
Вместо того, чтобы использовать обычный механизм отправки для обработки, вам действительно придется обрабатывать каждый метод и выполнять фильтрацию самостоятельно.
Шаг 1:
Определите свой процессор так, чтобы он поддерживал все аннотации, используя "*"
в качестве поддерживаемого типа аннотации. Это будет означать, что ваш процессор будет вызываться каждый раунд.
Шаг 2:
Используйте getRootElements
, чтобы получить весь набор элементов каждый раунд.
Шаг 3:
Создайте ElementScanner8
, чтобы пересечь любой элемент, который вы найдете, для поиска ExecutableElement
s. Если вы хотите верить, что переопределенные методы аннотируются с помощью @Override
, вы можете сделать быстрый фильтр для них. В противном случае просто посмотрите на них.
Шаг 4:
Теперь вам нужно проверить, отменяет ли метод метод с помощью аннотации, которую вы ищете. Нет простого способа получить методы, которые данный метод переопределил, поэтому вам нужно получить охватывающий элемент метода, посмотреть его superclass и реализованные интерфейсы (рекурсивно), получите их закрытые элементы, отфильтровать методы, а проверить, был ли он переопределен по рассматриваемому методу. Если это так, вы можете проверить аннотации, чтобы узнать, есть ли у вас какой-то интерес.
Шаг 5:
В этот момент вы должны иметь метод переопределения, переопределенный метод и зеркало аннотаций, которое вы искали, чтобы вы могли реализовать любую логику, которую вы хотели.
Ответ 2
в соответствии с javadoc javax.annotation.processing.Processor
в Jsr269-1.8
Аннотация присутствует, если она соответствует определению присутствия данный в AnnotatedConstruct. Короче говоря, аннотация рассматривается присутствовать в целях обнаружения, если оно прямо присутствует или присутствующих через наследование. Аннотации не считаются присутствующими из-за того, что он обернут аннотацией контейнера...
JavaDoc AnnotatedConstruct # getAnnotationsByType говорит, что он возвращает косвенно существующие аннотации, поэтому я думаю, что вы должны отсканировать методы и проверить, косвенно ли они аннотация с использованием этого вызова. Что-то в духе this.
Отказ от ответственности... не пробовал это;)
Ответ 3
Аннотации методов не наследуются. Аннотации типа могут быть наследованы с помощью аннотации "@Inherited".
Что вы можете сделать, так это определить функциональный интерфейс с унаследованной аннотацией типа, однако я не знаю, достаточно ли это для вас.
Ответ 4
Если эти аннотации доступны во время выполнения и вы хотите связаться с ними во время выполнения, вы можете использовать библиотеку Reflections.
Например:
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);