Процессоры аннотаций во время компиляции
Пишите AbstractProcessor для создания исходных файлов или проверки кода во время компиляции.
«Процессоры аннотаций во время компиляции» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Что такое процессоры аннотаций
Процессоры аннотаций (APT — инструмент обработки аннотаций) запускаются во время компиляции. Они анализируют аннотации исходного кода и могут создавать новые исходные файлы, файлы ресурсов или выдавать ошибки и предупреждения компилятора.
AbstractProcessor: базовый класс
Расширьте javax.annotation.processing.AbstractProcessor. Переопределите process(), чтобы обрабатывать аннотированные элементы. Объявите поддерживаемые аннотации и версию исходного кода Java.
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
@SupportedAnnotationTypes("com.example.GenerateBuilder")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class BuilderProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (Element e : roundEnv.getElementsAnnotatedWith(GenerateBuilder.class)) {
generateBuilder((TypeElement) e);
}
return true;
}
private void generateBuilder(TypeElement cls) { /* generate source */ }
}Регистрация процессора
Зарегистрируйте процессор в META-INF/services/javax.annotation.processing.Processor, указав полное имя класса. Инструменты сборки (Maven, Gradle) автоматически обнаружат его.
# META-INF/services/javax.annotation.processing.Processor
com.example.BuilderProcessorСоздание исходных файлов
Используйте processingEnv.getFiler().createSourceFile(), чтобы записать новый файл .java. Затем компилятор скомпилирует созданный файл в том же или следующем раунде.
JavaFileObject file = processingEnv.getFiler()
.createSourceFile("com.example.UserBuilder");
try (Writer w = file.openWriter()) {
w.write("package com.example;\n");
w.write("public class UserBuilder {\n");
w.write(" // generated builder\n");
w.write("}\n");
}Изучение модели элементов
Процессоры аннотаций работают с элементами Element, а не с классами Class: исходный код ещё не скомпилирован. Используйте TypeElement, VariableElement и ExecutableElement.
TypeElement classElement = (TypeElement) element;
String className = classElement.getSimpleName().toString();
List<VariableElement> fields = classElement.getEnclosedElements().stream()
.filter(e -> e.getKind() == ElementKind.FIELD)
.map(e -> (VariableElement) e)
.collect(Collectors.toList());Выдача ошибок компилятора
Вызовите processingEnv.getMessager().printMessage(), чтобы выдать ошибку, предупреждение или примечание. Так пользовательские аннотации ограничений сообщают о нарушениях во время компиляции.
processingEnv.getMessager().printMessage(
Diagnostic.Kind.ERROR,
"@GenerateBuilder requires at least one field",
element
);Многораундовая обработка
Обработка аннотаций происходит по раундам. Если вы создаёте файл, содержащий аннотации, процессор может снова запуститься в следующем раунде. roundEnv.processingOver() сообщает о последнем раунде.
if (roundEnv.processingOver()) {
// last round — write summary files or do cleanup
}Как работает Lombok
Lombok использует нестандартное расширение APT, которое изменяет AST существующих классов (что не разрешено спецификацией). Его аннотации, такие как @Data, @Builder и @Getter, напрямую добавляют методы в скомпилированный класс.
Генерация кода MapStruct
MapStruct создаёт типобезопасные реализации преобразователей во время компиляции. Он читает интерфейсы с аннотацией @Mapper и записывает реализации как обычные классы Java, не используя рефлексию во время выполнения.
@Mapper
public interface UserMapper {
UserDto toDto(User user);
User toEntity(UserDto dto);
}
// MapStruct generates: UserMapperImpl.java at compile timeТестирование процессоров аннотаций
Используйте google/compile-testing или Kapt (для Kotlin), чтобы писать модульные тесты процессоров. Передавайте строки исходного кода и проверяйте созданные файлы или ошибки компилятора.
JavaFileObject src = JavaFileObjects.forSourceString("Test",
"@GenerateBuilder public class Test { private String name; }");
Compilation c = Compiler.javac().withProcessors(new BuilderProcessor()).compile(src);
CompilationSubject.assertThat(c).succeeded();
CompilationSubject.assertThat(c).generatedSourceFile("TestBuilder");Упаковка процессора
Поместите процессор в отдельный модуль Maven. Модуль аннотаций, содержащий только аннотации, является зависимостью compile; модуль процессора использует область annotationProcessor и никогда не является зависимостью времени выполнения.
// build.gradle:
dependencies {
implementation "com.example:my-annotations:1.0"
annotationProcessor "com.example:my-processor:1.0"
}Быстрая проверка
Где регистрируют процессор аннотаций для автоматического обнаружения?
Итоги
Расширьте AbstractProcessor, зарегистрируйте процессор в META-INF/services, создавайте исходный код с помощью Filer и выдавайте ошибки с помощью Messager. Упаковывайте процессоры отдельно. Используйте compile-testing для модульных тестов. Это устраняет накладные расходы рефлексии во время выполнения.
Изучай Java с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 104
- Уроки
- 374
Часто задаваемые вопросы
Урок «Процессоры аннотаций во время компиляции» бесплатный?
Да — полный текст урока «Процессоры аннотаций во время компиляции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «Процессоры аннотаций во время компиляции»?
Пишите AbstractProcessor для создания исходных файлов или проверки кода во время компиляции. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Процессоры аннотаций во время компиляции»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Определение аннотаций: элементы и значения по умолчанию
- Политики хранения и типы целей
- Обработка аннотаций во время выполнения
- Процессоры аннотаций во время компиляции