Интерфейс обработчика аннотаций
- Все известные реализующие классы:
AbstractProcessor
public interface Processor
Обработка аннотаций происходит в последовательности раундов. На каждом раунде обработчик может быть запрошен для обработки подмножества аннотаций, найденных в файлах исходного кода и классе, сгенерированных предыдущим раундом. Входные данные для первого раунда обработки — это исходные данные для выполнения инструмента; эти исходные данные можно рассматривать как выходные данные виртуального нулевого раунда обработки. Если обработчик был запрошен для обработки в данном раунде, он будет запрошен для обработки в последующих раундах, включая последний раунд, даже если для обработки нет никаких аннотаций. Инфраструктура инструмента также может попросить обработчик обработать файлы, сгенерированные неявно в ходе работы инструмента.
Каждая реализация обработчика должна предоставлять публичный конструктор без аргументов, который будет использоваться инструментами для создания экземпляра обработчика. Инфраструктура инструмента будет взаимодействовать с классами, реализующими этот интерфейс, следующим образом:
- Если существующий объект обработчика не используется, для создания экземпляра обработчика инструмент вызывает конструктор без аргументов класса обработчика.
- Затем инструмент вызывает метод
initс соответствующейProcessingEnvironment. - После этого инструмент вызывает
getSupportedAnnotationTypes,getSupportedOptionsиgetSupportedSourceVersion. Эти методы вызываются только один раз за запуск, а не на каждом раунде. - По мере необходимости инструмент вызывает метод
processдля объекта обработчика; для каждого раунда не создается новый объект обработчика.
Инструмент использует процесс обнаружения для поиска обработчиков аннотаций и определения того, следует ли их запускать. Настроив инструмент, можно управлять набором потенциальных обработчиков. Например, для JavaCompiler список кандидатных обработчиков для запуска можно установить непосредственно или управлять им с помощью пути поиска, используемого для поиска по типу службы. Другие реализации инструмента могут иметь различные механизмы конфигурации, такие как параметры командной строки; для получения подробной информации обратитесь к документации конкретного инструмента. Какие обработчики инструмент запросит для выполнения, зависит от интерфейсов аннотаций присутствующих в корневых элементах, от того, какие интерфейсы аннотаций поддерживает обработчик, и от того, требует ли обработчик интерфейсов аннотаций, которые он обрабатывает. Обработчик будет запрошен для обработки подмножества поддерживаемых им интерфейсов аннотаций, возможно, пустого набора. Для данного раунда инструмент вычисляет набор интерфейсов аннотаций, присутствующих в элементах, заключенных в корневые элементы. Если присутствует хотя бы один интерфейс аннотации, то по мере того, как обработчики заявляют о поддержке интерфейсов аннотаций, они удаляются из набора несопоставленных интерфейсов аннотаций. Когда набор пуст или больше нет доступных обработчиков, раунд завершен. Если интерфейсы аннотаций отсутствуют, обработка аннотаций все же происходит, но только универсальные обработчики, которые поддерживают обработку всех интерфейсов аннотаций, "*", могут претендовать на (пустой) набор интерфейсов аннотаций.
Интерфейс аннотации считается присутствующим, если по крайней мере одна аннотация этого интерфейса присутствует в элементе, заключенном в корневые элементы раунда. Для этой цели параметр типа считается заключенным в его обобщенный элемент. Для этой цели элемент пакета не считается содержащим классы и интерфейсы верхнего уровня в этом пакете. (Корневой элемент, представляющий пакет, создается при обработке файла package-info.) Аналогично, для этой цели элемент модуля не считается содержащим пакеты в этом модуле. (Корневой элемент, представляющий модуль, создается при обработке файла module-info.) Аннотации на использовании типов, в отличие от аннотаций на элементах, игнорируются при вычислении наличия интерфейса аннотации.
Аннотация считается присутствующей, если она соответствует определению наличия, данному в AnnotatedConstruct. Кратко, аннотация считается присутствующей для целей обнаружения, если она непосредственно присутствует или присутствует через наследование. Аннотация не считается присутствующей благодаря тому, что она обернута контейнерной аннотацией. В операционном плане это эквивалентно тому, что аннотация присутствует на элементе, если и только если она будет включена в результаты вызова Elements.getAllAnnotationMirrors(Element) для этого элемента. Поскольку аннотации внутри контейнерных аннотаций не считаются присутствующими, для правильной обработки повторяемых интерфейсов аннотаций, обработчики должны включать как интерфейс повторяемой аннотации, так и интерфейс содержащей аннотации в набор поддерживаемых интерфейсов аннотаций обработчика.
Обратите внимание, что если обработчик поддерживает "*" и возвращает
true, все аннотации заявляются. Следовательно, универсальный обработчик, используемый, например, для реализации дополнительных проверок на валидность, должен возвращать false, чтобы не препятствовать выполнению других подобных проверок.
Если обработчик генерирует незахваченное исключение, инструмент может прекратить работу других активных обработчиков аннотаций. Если обработчик вызывает ошибку, текущий раунд завершится, а последующий раунд укажет на возникновение ошибки. Поскольку обработчики аннотаций выполняются в кооперативной среде, обработчик должен генерировать незахваченное исключение только в ситуациях, когда восстановление или отчет об ошибке невозможны.
Среда инструмента не обязана поддерживать обработчики аннотаций, которые обращаются к ресурсам среды, как в пределах каждого раунда, так и межраундово, в многопоточном режиме.
Если методы, возвращающие конфигурационную информацию об обработчике аннотаций, возвращают null, возвращают другие недопустимые входные данные или генерируют исключение, инфраструктура инструмента должна рассматривать это как условие ошибки.
Для повышения устойчивости при работе в разных реализациях инструмента обработчик аннотаций должен обладать следующими свойствами:
- Результат обработки заданного входного значения не зависит от наличия или отсутствия других входных значений (ортогональность).
- Обработка одного и того же входного значения порождает одинаковый результат (согласованность).
- Обработка входного значения A, за которой следует обработка входного значения B, эквивалентна обработке B, а затем A (коммутативность)
- Обработка входного значения не зависит от наличия выходного значения других обработчиков аннотаций (независимость)
Интерфейс Filer обсуждает ограничения на то, как обработчики могут работать с файлами.
- Примечание к API:
- Реализаторам этого интерфейса может быть удобно расширить
AbstractProcessor, а не реализовывать этот интерфейс напрямую. - С:
- 1.6
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Iterable |
getCompletions |
Возвращает инфраструктуре инструмента перечислитель предлагаемых завершений аннотации. |
Set |
getSupportedAnnotationTypes() |
Возвращает имена интерфейсов аннотаций, поддерживаемых этим обработчиком. |
Set |
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; если у процессора нет дополнений, которые можно предложить на основе предоставленной информации, может быть возвращён пустой итерируемый набор. Процессор также может вернуть одно дополнение со строкой значения 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, 2025, 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://download.java.net/java/early_access/jdk24/docs/api/java.compiler/javax/annotation/processing/Processor.html