Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Concetti base del Java annotation processing

Analizziamo i concetti basilari del Java annotation processing con un'analisi del ruolo dell'annotazione @Convert nell'individuazione delle classi e del processore di annotazioni nell'elaborazione dei file sorgenti passati al compilatore.
Analizziamo i concetti basilari del Java annotation processing con un'analisi del ruolo dell'annotazione @Convert nell'individuazione delle classi e del processore di annotazioni nell'elaborazione dei file sorgenti passati al compilatore.
Link copiato negli appunti

L'annotazione @Convert

L'annotazione @Convert serve ad individuare quali classi saranno soggette alla conversione in ContentValue. La definizione dell'annotazione è la seguente:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Convert {
}

Come descritto in precedenza, la definizione di @Convert è collocata nel progetto "Annotation". Ad esempio, la classe Persona sarà decorata in questo modo:

@Convert
public class Persona {
	public String nome;
	public String cognome;
	public int eta;
	public int peso;
}

Una particolarità importante da tenere a mente è che le annotazioni non vengono ereditate. Annotare la classe Persona non significa quindi annotare automaticamente anche tutte le classi che ne derivano.

Il processore di annotazioni

Un processore di annotazioni è una classe Java che consente di elaborare i file sorgenti passati al compilatore. Gli AP vengono agganciati alla fase di compilazione. Tra le loro particolarità bisogna sicuramente citare il fatto che vengono eseguiti in virtual machine separate. Normalmente un AP deriva dalla classe AbstractProcessor. Di seguito è riportata la struttura base di un AP.

package it.html.jap;
public class ConvertProcessor extends AbstractProcessor {
    @Override
    public synchronized void init(ProcessingEnvironment env){ ... }
    @Override
    public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { ... }
    @Override
    public Set<String> getSupportedAnnotationTypes() { ... }
    @Override
    public SourceVersion getSupportedSourceVersion() { ... }
}

Analizziamo brevemente lo scopo dei vari metodi:

Metodo Descrizione
init(ProcessingEnvironment env) Viene invocato dall'annotation processing, prima dell'analisi delle classi da compilare, con un parametro di tipo ProcessingEnviroment che fornisce delle classi di utilià che si vedranno in seguito.
process(Set<? extends TypeElement> annotations, RoundEnvironment env) Questo metodo contiene il codice per effettuare lo scan, elaborare le annotazioni e generare i file. Il parametro RoundEnviroment viene utilizzato per recuperare le classi con le annotazioni gestite dal processore.
getSupportedAnnotationTypes() Restituisce l'insieme di annotazioni gestite dal processore.
getSupportedSourceVersion() Specifica quale versione di Java è supportata. Per indicare che si vuole supportare fino all'ultima versione di Java disponibile deve restituire la costante SourceVersion.latestSupported().

Metodo init

È il metodo usato per inizializzare il processore di annotazioni. Normalmente dal parametro ProcessingEnvironment, passato al metodo init, si recuperano i riferimenti a:

  • elements: una classe di utilità per lavorare con gli Element.
  • types: classe di utilità per lavorare con i TypeMirror.
  • filer: necessario a generare i file in output.

I processori di annotazione analizzano i sorgenti Java. Ogni componente della definizione di una classe viene identificato da un element. Esistono vari tipi di element che si differenziano in base a quello che rappresentano: il package, la classe, gli attributi o i metodi. Nel codice sottostante, per ogni parte della definizione della classe, all'interno dei commenti, viene riportato l'element associato.

package it.html.jap;  // PackageElement
public class Persona {  // TypeElement
  private int eta;      // VariableElement
  private String nome;  // VariableElement
  public Persona () {}  // ExecuteableElement
  public void setNome (  // ExecuteableElement
    String value         // TypeElement
  ) { ... }
  public void setEta (  // ExecuteableElement
    int value           // TypeElement
  ) { ... }
}

Bisogna sempre tener presente che i file Java contengono codice strutturato. La rappresentazione con la quale lavorano i processori è una struttura ad albero di elementi. Per esempio, se si ha un TypeElement che rappresenta public class Prova, si può navigare attraverso i suoi figli mediante un codice molto simile al seguente:

TypeElement provaClass = ... ;
for (Element item : provaClass.getEnclosedElements()){ // itera sugli elementi figli
	...
}

TypeElement rappresenta gli elementi che si trovano nei file .java come ad esempio le classi. TypeElement, però non contiene le informazioni relative alla classe stessa. Dal TypeElement si possono ottenere informazioni riguardanti la dichiarazione della classe, come ad esempio il suo nome, ma non informazioni inerenti la sua gerarchia (ad esempio la classe padre). Questo tipo di informazioni è accessibile mediante un oggetto di tipo TypeMirror che si può ottenere da un element mediante il metodo element.asType().

Ti consigliamo anche