Интерфейс обработчика аннотаций
- Все известные реализующие классы:
AbstractProcessor
public interface Processor
Обработка аннотаций происходит в последовательности раундов. В каждом раунде обработчик может быть запрошен для обработки подмножества аннотаций, найденных в исходных и скомпилированных файлах, полученных в предыдущем раунде. Ввод для первого раунда обработки — исходные данные для выполнения инструмента; эти исходные данные можно рассматривать как результат виртуального нулевого раунда обработки. Если обработчик был запрошен для обработки в данном раунде, он будет запрошен для обработки в последующих раундах, включая последний раунд, даже если для него нет аннотаций для обработки. Инфраструктура инструмента может также запросить от обработчика обработку файлов, генерируемых неявно в ходе работы инструмента.
Каждая реализация Processor должна предоставлять публичный конструктор без аргументов, который будет использоваться инструментами для создания экземпляра обработчика. Инфраструктура инструмента будет взаимодействовать с классами, реализующими этот интерфейс, следующим образом:
- Если существующий объект
Processorне используется, для создания экземпляра обработчика инструмент вызывает конструктор без аргументов класса обработчика. - Далее, инструмент вызывает метод
initс соответствующимProcessingEnvironment. - После этого инструмент вызывает
getSupportedAnnotationTypes,getSupportedOptionsиgetSupportedSourceVersion. Эти методы вызываются только один раз за выполнение, а не в каждом раунде. - По мере необходимости инструмент вызывает метод
processдля объектаProcessor; новый объектProcessorне создаётся для каждого раунда.
Инструмент использует процесс обнаружения для поиска обработчиков аннотаций и определения, следует ли их запускать. Настраивая инструмент, можно контролировать набор потенциальных обработчиков. Например, для JavaCompiler список кандидатных обработчиков для запуска можно установить напрямую или контролировать с помощью пути поиска, используемого для поиска по стилю службы. Другие реализации инструмента могут иметь различные механизмы настройки, такие как параметры командной строки; для получения подробностей см. документацию конкретного инструмента. Какие обработчики инструмент просит запустить — это функция интерфейсов аннотаций присутствующих в корневых элементах, какие интерфейсы аннотаций поддерживает обработчик и заявляет ли обработчик обрабатываемые интерфейсы аннотаций. Обработчику будет запрошено обработать подмножество поддерживаемых им интерфейсов аннотаций, возможно, пустое множество. Для данного раунда инструмент вычисляет набор интерфейсов аннотаций, которые присутствуют в элементах, вложенных в корневые элементы. Если хотя бы один интерфейс аннотации присутствует, по мере того как обработчики заявляют о поддержке интерфейсов аннотаций, они удаляются из набора несопоставленных интерфейсов аннотаций. Когда набор пуст или больше нет доступных обработчиков, раунд завершён. Если интерфейсы аннотаций отсутствуют, обработка аннотаций всё ещё происходит, но только универсальные обработчики, которые поддерживают обработку всех интерфейсов аннотаций, "*", могут заявить о поддержке пустого набора интерфейсов аннотаций.
Интерфейс аннотации считается присутствующим, если присутствует хотя бы одна аннотация этого интерфейса на элементе, вложенном в корневые элементы раунда. В этой цели, параметр типа считается вложенным в свой обобщённый элемент. В этой цели элемент пакета не считается содержащим классы и интерфейсы верхнего уровня в этом пакете. (Корневой элемент, представляющий пакет, создается при обработке файла package-info. Аналогично, в этой цели элемент модуля не считается содержащим пакеты в этом модуле. (Корневой элемент, представляющий модуль, создается при обработке файла module-info. Аннотации на использованиях типов, в отличие от аннотаций на элементах, игнорируются при вычислении присутствия или отсутствия интерфейса аннотации.
Аннотация считается присутствующей, если она соответствует определению присутствия, данному в AnnotatedConstruct. Вкратце, аннотация считается присутствующей для целей обнаружения, если она непосредственно присутствует или присутствует через наследование. Аннотация не считается присутствующей в силу того, что она обернута контейнерной аннотацией. Оперативно это эквивалентно тому, что аннотация присутствует на элементе, если и только если она будет включена в результаты вызова Elements.getAllAnnotationMirrors(Element) на этом элементе. Поскольку аннотации внутри контейнерных аннотаций не считаются присутствующими, для правильной обработки повторяемых интерфейсов аннотаций, обработчикам рекомендуется включить в набор поддерживаемых интерфейсов аннотаций обработчика как сам интерфейс повторяемой аннотации, так и содержащий его интерфейс аннотации.
Обратите внимание, что если обработчик поддерживает "*" и возвращает
true, все аннотации считаются обработанными. Поэтому универсальный обработчик, используемый, например, для реализации дополнительных проверок на валидность, должен возвращать false, чтобы не препятствовать запуску других таких проверяющих элементов.
Если обработчик сгенерирует необработанное исключение, инструмент может прекратить работу других активных обработчиков аннотаций. Если обработчик создаст ошибку, текущий раунд завершится, а последующий раунд укажет на возникновение ошибки. Поскольку обработчики аннотаций работают в кооперативной среде, обработчик должен генерировать необработанное исключение только в ситуациях, когда восстановление от ошибок или отчёт невозможны.
Среда инструмента не обязана поддерживать обработчики аннотаций, которые обращаются к ресурсам среды, как в рамках каждого раунда, так и межраундовом режиме, в многопоточном режиме.
Если методы, возвращающие конфигурационную информацию об обработчике аннотаций, возвращают null, возвращают другой неверный ввод или генерируют исключение, инфраструктура инструмента должна рассматривать это как ошибочное условие.
Для надёжной работы в различных реализациях инструмента обработчик аннотаций должен обладать следующими свойствами:
- Результат обработки заданного входного значения не зависит от присутствия или отсутствия других входных данных (ортогональность).
- Обработка одного и того же входного значения приводит к одному и тому же результату (согласованность).
- Обработка входного значения A, за которой следует обработка входного значения B, эквивалентна обработке B, а затем A (коммутативность)
- Обработка входного значения не зависит от наличия выходного значения других обработчиков аннотаций (независимость)
Интерфейс Filer обсуждает ограничения, налагаемые на обработчики при работе с файлами.
- Примечание API:
- Реализаторам этого интерфейса может быть удобно расширить
AbstractProcessor, а не реализовывать этот интерфейс напрямую. - С:
- 1.6
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Iterable<? extends Completion> |
getCompletions |
Возвращает инструменту инфраструктуры итератор предложенных дополнений к аннотации. |
Set<String> |
getSupportedAnnotationTypes() |
Возвращает имена поддерживаемых этим обработчиком интерфейсов аннотаций. |
Set<String> |
getSupportedOptions() |
Возвращает параметры, распознаваемые этим обработчиком. |
SourceVersion |
getSupportedSourceVersion() |
Возвращает последнюю поддерживаемую версию исходного кода для этого обработчика аннотаций. |
void |
init |
Инициализирует обработчик с помощью среды обработки. |
boolean |
process |
Обрабатывает набор интерфейсов аннотаций на элементах типа, полученных из предыдущего раунда, и возвращает, заявляет ли этот обработчик о поддержке этих интерфейсов аннотаций. |
Подробное описание методов
getSupportedOptions
Set<String> getSupportedOptions()
getOptions. Каждая возвращаемая строка должна быть последовательностью идентификаторов, разделённых точками:
- SupportedOptionString:
- Identifiers
- Identifiers:
- Identifier
- Identifier
.Identifiers- Identifier:
- Синтаксический идентификатор, включающий ключевые слова и литералы
Инструмент может использовать эту информацию, чтобы определить, являются ли предоставленные пользователем опции нераспознанными ни одним процессором, в этом случае он может захотеть сообщить об ошибке.
- Возвращает:
- опции, распознаваемые этим процессором, или пустой набор, если таковых нет
- См. также:
getSupportedAnnotationTypes
Set<String> getSupportedAnnotationTypes()
name.*", представляющий набор всех интерфейсов аннотаций с каноническими именами, начинающимися с "name.". В любом из этих случаев имя интерфейса аннотации может быть необязательно предваряемо именем модуля, за которым следует символ
"/". Например, если процессор поддерживает
"a.B", это может включать несколько интерфейсов аннотаций с именами
a.B, которые находятся в разных модулях. Чтобы поддерживать только
a.B в модуле foo, используйте вместо этого "foo/a.B". Если имя модуля указано, соответствует только аннотация в этом модуле. В частности, если имя модуля указано в среде, где модули не поддерживаются, например, в среде обработки аннотаций, настроенной для версии исходного кода без модулей, то интерфейсы аннотаций с именем модуля не соответствуют. Наконец, "*" само по себе представляет набор всех интерфейсов аннотаций, включая пустой набор. Обратите внимание, что процессор не должен заявлять "*" , если он фактически не обрабатывает все файлы; объявление ненужных аннотаций может привести к снижению производительности в некоторых средах. Каждая возвращаемая строка должна соответствовать следующей грамматике:
где TypeName и ModuleName определены в Спецификации языка Java (6.5 Определение смысла имени).
- SupportedAnnotationTypeString:
- ModulePrefixopt TypeName DotStaropt
*- ModulePrefix:
- ModuleName
/- DotStar:
.*
- Примечание API:
- При работе в среде, поддерживающей модули, процессорам рекомендуется включать префикс модуля при описании поддерживаемых интерфейсов аннотаций. Метод
AbstractProcessor.getSupportedAnnotationTypesпредоставляет поддержку удаления префикса модуля при работе в среде без модулей. - Возвращает:
- имена интерфейсов аннотаций, поддерживаемых этим процессором, или пустой набор, если таковых нет
- См. Спецификацию языка Java:
- 3.8 Идентификаторы
- См. также:
getSupportedSourceVersion
SourceVersion getSupportedSourceVersion()
- Возвращает:
- последнюю поддерживаемую версию исходного кода этим процессором аннотаций
- См. также:
init
void init(ProcessingEnvironment processingEnv)
- Параметры:
-
processingEnv- среда для использования функций, предоставляемых инструментом обработки процессору
process
boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
true возвращается, интерфейсы аннотаций объявляются, и последующим процессорам не будет предложено их обрабатывать; если false возвращается, интерфейсы аннотаций не объявляются, и последующим процессорам может быть предложено их обработать. Процессор может всегда возвращать то же булево значение или изменять результат, основываясь на своих собственных критериях. Входящий набор будет пустым, если процессор поддерживает
"*", и у корневых элементов нет аннотаций. Процессор
Processor должен корректно обрабатывать пустой набор аннотаций.
- Параметры:
-
annotations- интерфейсы аннотаций, запрошенные для обработки -
roundEnv- среда для информации о текущем и предыдущем раунде - Возвращает:
- были ли интерфейсы аннотаций объявлены этим процессором
getCompletions
Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText)
int , значение которого должно находиться в диапазоне от 1 до 10 или строчный член, который должен быть распознан известной грамматикой, например, регулярным выражением или URL-адресом. Поскольку моделируются неполные программы, некоторые параметры могут содержать только частичную информацию или быть
null. По крайней мере один из element и userText должен быть не-null. Если element не-null, annotation и member могут быть
null. Процессоры не должны выбрасывать NullPointerException , если некоторые параметры null; если процессор не может предложить завершения на основе предоставленной информации, может быть возвращён пустой итерируемый набор. Процессор также может вернуть одно завершение со строкой значения пустым и сообщением, описывающим, почему нет завершений.
Завершения информативны и могут отражать дополнительные проверки допустимости, выполняемые процессорами аннотаций. Например, рассмотрим простую аннотацию:
@MersennePrime {
int value();
}
(Простое число Мерсенна — простое число вида 2n - 1.) Учитывая AnnotationMirror для этого интерфейса аннотации, можно вернуть список всех таких простых чисел в диапазоне int , не исследуя другие аргументы в getCompletions: Более информативный набор завершений включал бы количество каждого простого числа:import static javax.annotation.processing.Completions.*; ... return List.of(of("3"), of("7"), of("31"), of("127"), of("8191"), of("131071"), of("524287"), of("2147483647"));
Однако, еслиreturn List.of(of("3", "M2"), of("7", "M3"), of("31", "M5"), of("127", "M7"), of("8191", "M13"), of("131071", "M17"), of("524287", "M19"), of("2147483647", "M31"));
userText доступен, можно проверить, являются ли только некоторые простые числа Мерсенна допустимыми. Например, если пользователь ввёл:
@MersennePrime(1
значение userText будет "1"; и только два из простых чисел являются возможными завершениями:
return Arrays.asList(of("127", "M7"),
of("131071", "M17"));
Иногда не существует допустимого завершения. Например, нет простого числа Мерсенна в диапазоне, начинающегося с 9:
@MersennePrime(9
Соответствующий ответ в этом случае — вернуть пустой список завершений, или одно пустое завершение с полезным сообщениемreturn Collections.emptyList();
return Arrays.asList(of("", "No in-range Mersenne primes start with 9"));
- Параметры:
-
element- элемент, к которому применяется аннотация -
annotation- (возможно, частичная) аннотация, применяемая к элементу -
member- член аннотации, для которого нужно вернуть возможные завершения -
userText- текст исходного кода, который нужно завершить - Возвращает:
- предлагаемые завершения аннотации
© 1993, 2021, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/17/docs/api/java.compiler/javax/annotation/processing/Processor.html