2012-05-12 13 views
5

Dies ist das erste Mal, dass ich einen Annotation Processor schreibe und ich möchte ihn programmgesteuert aufrufen. Ist es möglich?Programmatisch Annotation Processors aufrufen

Ich habe kleine Code für den Prozessor geschrieben:

@SupportedAnnotationTypes({"app.dev.ems.support.annotation.HBMModel"}) 
public class HBMModelProcessor extends AbstractProcessor { 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
     Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(HBMModel.class); 
     System.out.println(elements); 
     return true; 
    } 

} 

Wenn ich nun den Prozess Methode aufrufen wollen, dann, wie kann ich dies tun? Kann ich es auf folgende Weise tun:

HBMModelProcessor modelProcessor = new HBMModelProcessor(); 
modelProcessor.process(annotations, roundEnv) 

Alle Informationen werden mir sehr hilfreich sein.

Danke.

Antwort

1

Sie können die Java-Compiler mit Annotations Prozessoren nennen, programmatisch innerhalb des gleichen Prozesses, wie folgt aus:

import com.sun.tools.javac.processing.PrintingProcessor; 
import fi.jumi.actors.generator.JavaSourceFromString; 
import org.junit.*; 
import org.junit.rules.TemporaryFolder; 

import javax.annotation.processing.Processor; 
import javax.tools.*; 
import javax.tools.JavaCompiler.CompilationTask; 
import java.io.IOException; 
import java.util.Arrays; 

import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.Matchers.is; 

public class ExampleTest { 

    @Rule 
    public final TemporaryFolder tempDir = new TemporaryFolder(); 

    @Test 
    public void example() throws IOException { 
     JavaFileObject src = new JavaSourceFromString(
       "com.example.GuineaPig", 
       "package com.example;\n" + 
       "public interface GuineaPig {\n" + 
       " void foo();\n" + 
       "}" 
     ); 
     compile(new PrintingProcessor(), src); 
    } 

    private void compile(Processor processor, JavaFileObject... compilationUnits) throws IOException { 
     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 
     StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); 
     fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tempDir.getRoot())); 

     CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, Arrays.asList(compilationUnits)); 
     task.setProcessors(Arrays.asList(
       processor 
     )); 
     boolean success = task.call(); 
     for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { 
      System.err.println(diagnostic); 
     } 
     assertThat("compile succeeded", success, is(true)); 
    } 
} 

Wenn Sie den Anruf setProcessors entfernen Sie dann wird es Annotation Prozessoren erkennt automatisch, basierend auf den META-INF/services/javax.annotation.processing.Processor Dateien auf Klassenpfad.

3

Dies ist ein Link zu my answer to a similar question.

Sie können Annotationsverarbeitung wie Sie in Ihrer Frage vorschlagen, aber Sie müssten die annotations und roundEnv produzieren.

Die beabsichtigte Verwendung der Annotationsverarbeitung erfolgt während der Kompilierung. Ich empfehle einen zweistufigen Kompilierungsprozess.

  1. Kompilieren Sie Ihren Annotationsprozessor und zugehörige Dateien auf die übliche Weise.
  2. kompilieren Sie die anderen Dateien (mit einem Compiler, der Annotationsverarbeitung unterstützt). Sie können an den Compiler auf einige Argumente haben: den Prozessor Pfad, den Klassennamen des Prozessors etc.

Der Compiler wird die annotations und roundEnv Variablen und eine Instanz der Prozessor erzeugen. (Die meisten Compiler erfordern, dass Ihr Prozessor öffentlich ist und einen öffentlichen Konstruktor hat.) Der Compiler ruft dann die process Methode auf.

+0

Danke für die Antwort. Also gibt es keine Möglichkeit, diese beiden Variablen "Annotations" und "roundEnv" zu bekommen? –

+0

Natürlich gibt es eine Möglichkeit, "Annotationen" und "roundEnv" zu erhalten. 'Anmerkungen = new HashSet (); Anmerkungen. addiere (/ * deine Annotationen * /); 'und' roundEnv = new RoundEnvironment() {/ * implementation * /} 'Versuchst du, deinen Prozessor zu testen? Sie könnten wahrscheinlich ein spöttisches Framework verwenden. – emory

+0

@emory, Ich möchte einen Annotationsprozessor Unit-Test. Und ein Beispiel wäre willkommen, da dies der erste Google-Eintrag ist. – Snicolas