Интерфейс Processor
- Все известные реализующие классы:
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 |
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; если процессор не может предложить варианты завершения на основе предоставленных сведений, можно вернуть пустой итерируемый объект. Процессор также может вернуть один вариант завершения с пустой строкой значения и сообщением, объясняющим отсутствие вариантов.
Варианты завершения носят информационный характер и могут учитывать дополнительные проверки корректности, выполняемые процессорами аннотаций. Например, рассмотрим простую аннотацию:
@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://docs.oracle.com/en/java/javase/25/docs/api/java.compiler/javax/annotation/processing/Processor.html