Java Academy · Lezione

Annotation processor a compile time

Scriva un AbstractProcessor per generare file sorgente o validare il codice durante la compilazione.

Lezione 4 di 413 passaggi

Annotation processor a compile time è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Che cosa sono i processori di annotazioni?

I processori di annotazioni (APT — Annotation Processing Tool) vengono eseguiti durante la compilazione. Analizzano le annotazioni del codice sorgente e possono generare nuovi file sorgente, file di risorse oppure produrre errori e avvisi del compilatore.

AbstractProcessor: la classe base

Estenda javax.annotation.processing.AbstractProcessor. Esegua l'override di process() per gestire gli elementi annotati. Dichiari le annotazioni supportate e la versione del codice sorgente 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 */ }
}

Registrare il processore

Registri il processore in META-INF/services/javax.annotation.processing.Processor indicando il nome completo della classe. Gli strumenti di build (Maven, Gradle) lo rilevano automaticamente.

# META-INF/services/javax.annotation.processing.Processor
com.example.BuilderProcessor

Generare file sorgente

Utilizzi processingEnv.getFiler().createSourceFile() per scrivere un nuovo file .java. Il compilatore compila quindi il file generato nello stesso round o in quello successivo.

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");
}

Esaminare il modello degli elementi

I processori di annotazioni lavorano con gli Element (non con le Class: il codice sorgente non è ancora compilato). Utilizzi TypeElement, VariableElement ed 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());

Generare errori del compilatore

Chiami processingEnv.getMessager().printMessage() per generare errori, avvisi o note. È così che le annotazioni personalizzate dei vincoli segnalano le violazioni in fase di compilazione.

processingEnv.getMessager().printMessage(
    Diagnostic.Kind.ERROR,
    "@GenerateBuilder requires at least one field",
    element
);

Elaborazione in più round

L'elaborazione delle annotazioni avviene in round. Se genera un file che contiene annotazioni, il processore può essere eseguito nuovamente nel round successivo. roundEnv.processingOver() segnala il round finale.

if (roundEnv.processingOver()) {
    // last round — write summary files or do cleanup
}

Lombok dietro le quinte

Lombok utilizza un'estensione APT non standard che modifica l'AST delle classi esistenti (operazione non consentita dalla specifica). Le sue annotazioni, come @Data, @Builder e @Getter, generano direttamente i metodi nella classe compilata.

Generazione del codice con MapStruct

MapStruct genera implementazioni type-safe dei mapper in fase di compilazione. Legge le interfacce annotate con @Mapper e scrive le implementazioni come normali classi Java, senza alcun uso della reflection in fase di esecuzione.

@Mapper
public interface UserMapper {
    UserDto toDto(User user);
    User toEntity(UserDto dto);
}
// MapStruct generates: UserMapperImpl.java at compile time

Testare i processori di annotazioni

Utilizzi google/compile-testing o Kapt (per Kotlin) per sottoporre i processori a unit test. Fornisca stringhe sorgente e verifichi i file generati o gli errori del compilatore.

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");

Creare il package del processore

Inserisca il processore in un modulo Maven separato. Il modulo delle annotazioni (contenente solo le annotazioni) è una dipendenza compile; il modulo del processore ha ambito annotationProcessor e non deve mai essere una dipendenza in fase di esecuzione.

// build.gradle:
dependencies {
    implementation "com.example:my-annotations:1.0"
    annotationProcessor "com.example:my-processor:1.0"
}

Verifica rapida

Dove si registra un processore di annotazioni per il rilevamento automatico?

Riepilogo

Estenda AbstractProcessor, registri il processore in META-INF/services, generi il codice sorgente con Filer e produca gli errori con Messager. Inserisca i processori in package separati. Utilizzi compile-testing per gli unit test. In questo modo si elimina il sovraccarico della reflection in fase di esecuzione.

Gratis per iniziare

Impara Java con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
104
Lezioni
374

Domande Frequenti

La lezione «Annotation processor a compile time» è gratuita?

Sì — il testo completo di «Annotation processor a compile time» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Annotation processor a compile time»?

Scriva un AbstractProcessor per generare file sorgente o validare il codice durante la compilazione. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Annotation processor a compile time»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Definire annotazioni: elementi e valori predefiniti
  2. Politiche di conservazione e tipi di target
  3. Elaborazione delle annotazioni a runtime
  4. Annotation processor a compile time
← Torna a Java Academy