2012-05-12 11 views
5

Esta es la primera vez que escribo un procesador de anotaciones y deseo invocarlo mediante programación. ¿Es posible?Invocar mediante programación los procesadores de anotación

He escrito pequeño código para el procesador:

@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; 
    } 

} 

Ahora Si quiero invocar el método de proceso, entonces, ¿cómo puedo hacer esto? ¿Puedo hacerlo de la siguiente manera:

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

Cualquier información será de gran ayuda para mí.

Gracias.

Respuesta

1

puede llamar al compilador de Java, con procesadores de anotación mediante programación, dentro del mismo proceso, así:

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

Si se quita la llamada a setProcessors entonces se detectará procesadores de anotación automáticamente en función de los META-INF/services/javax.annotation.processing.Processor archivos classpath.

3

Este es un enlace a my answer to a similar question.

Puede hacer el procesamiento de anotación de la manera que sugiere en su pregunta, pero de alguna manera tendría que generar el annotations y el roundEnv.

El uso previsto del proceso de anotación es durante la compilación. Recomiendo un proceso de compilación de dos pasos.

  1. Recopila el procesador de anotaciones y los archivos relacionados de la forma habitual.
  2. compila los otros archivos (utilizando un compilador que admite el proceso de anotación). Puede que tenga que algunos argumentos para el compilador: el camino del procesador, el nombre de la clase del procesador, etc.

El compilador producirá las variables annotations y roundEnv y una instancia de su procesador. (La mayoría de los compiladores requieren que su procesador sea público y tenga un constructor público). El compilador invocará el método process.

+0

Gracias por su respuesta. Entonces, ¿no hay forma de obtener estas dos variables 'annotations' y' roundEnv'? –

+0

Por supuesto, hay una forma de obtener 'annotations' y' roundEnv'. 'anotaciones = nuevo HashSet (); anotaciones agregue (/ * sus anotaciones * /); 'y' roundEnv = new RoundEnvironment() {/ * implementation * /} '¿Está tratando de probar la unidad de su procesador? Probablemente puedas usar un marco de burla. – emory

+0

@emory, quiero probar en unidad un procesador de anotación. Y una muestra sería bienvenida ya que esta es la primera entrada de Google. – Snicolas

Cuestiones relacionadas