2010-09-18 22 views
15

escribí una anotación personalizada que contiene los metadatos de una propiedad y un AnnotationProcessor:Java 6 - procesador de anotación y el código Además

@SupportedAnnotationTypes({"<package>.Property"}) 
public class PropertyProcessor extends AbstractProcessor { 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, 
      RoundEnvironment roundEnv) { 
     // Get messager object 
     Messager messager = processingEnv.getMessager(); 
     // Iterate through the annotations 
     for(TypeElement typeElement : annotations) { 
      // Iterate through the annotated elements 
      for(Element element : roundEnv.getElementsAnnotatedWith(typeElement)) { 
       // Get Property annotation 
       Property property = element.getAnnotation(Property.class); 

      } 
     } 
     return false; 
    } 

} 

Aquí es la cuestión, he utilizado Javassist antes, pero fue en función del cargador de clases y creo que no es apropiado para aplicaciones OSGi. Quiero cambiar el bytecode generado cuando se compila una clase con la anotación Property.

+0

una pregunta: ¿por qué es necesario? ¿No se puede lograr de otra manera? – Bozho

+0

sin utilizar APT o esta API, tendré que anotar los métodos setter y getter para cada propiedad, pero si esto funciona, tendré un control total sobre cómo se generará el código. esta no es una pregunta comercial pura, quiero saber si esto es posible o no –

Respuesta

5

La respuesta breve es: se supone que no debe cambiar el código fuente durante el proceso de anotación.

Recientemente tuve una situación en la que esa respuesta no fue satisfactoria (consulte this question). Mi solución fue agregar programáticamente el código que necesitaba usando la API interna javac. Ver my answer to my own question para más detalles.

Me inspiré en esto desde Project Lombok, comenzando con su código fuente y tirando todo lo que no necesitaba. No creo que encuentres un punto de partida mucho mejor.

Por cierto, Javassist probablemente no ayude, porque se trata de un árbol fuente, no con código de bytes. Si desea utilizar una biblioteca de manipulación de código de bytes, puede hacerlo de forma estática después de la compilación o dinámicamente al cargar las clases, pero no durante el proceso de anotación, porque es un paso de precompilación.

6

¿Has probado Google Guice?

Google Guice le permite hacer un poco de Programación Orientada a Aspectos mediante la interceptación de métodos. Si eso es todo lo que necesita hacer, puede implementar un MethodInterceptor que le permitirá anular los métodos en tiempo de ejecución. Es realmente bueno para aislar las preocupaciones transversales.

Por ejemplo, digamos que usted desea evitar que un ciertos métodos de ser ejecutado los fines de semana, puede anotar como así:

@Property 
public class SomeClass { 
    public Receipt doSometing() { 
     // Do something 
    } 
} 

definir un MethodInterceptor:

public class PropertyInterceptor implements MethodInterceptor { 
    public Object invoke(MethodInvocation invocation) throws Throwable { 
    // For example prevent the classes annotated with @Property 
    // from being called on weekends 
    Calendar today = new GregorianCalendar(); 
    if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) { 
     throw new IllegalStateException(
      invocation.getMethod().getName() + " not allowed on weekends!"); 
    } 
    return invocation.proceed(); 
    } 
} 

Y luego se unen el interceptor de la anotación:

public class PropertyModule extends AbstractModule { 
    protected void configure() { 
     PropertyInterceptor propertyInterceptor = new PropertyInterceptor();   
     bindInterceptor(Matchers.annotatedWith(Property.class), 
     Matchers.any(), propertyInterceptor); 
    } 
} 
1

El procesamiento de anotaciones no está destinado a alterar clases existentes: es solo para generar código/recursos adicionales (clase por clase); de lo contrario, se encontrará con problemas al volver a compilar únicamente las fuentes modificadas.

Hace algún tiempo he intentado Spoon para un problema similar: Me gustaba la idea de un procesador programa mucho (y la integración IDE incluso más), pero no era muy estable en el tiempo ...

Dependiendo de su caso de uso, una herramienta AOP (p. Ej .: AspectJ) podría adaptarse mejor que Spoon y, por supuesto, siempre podría usar un generador de código fuente o implementar una DSL completa (mire la fantástica Xtext) .

Dependiendo del tamaño, la tasa de rotación y la "inercia intelectual" de sus compañeros de equipo - usted podría estar mejor soportando los dolores de java simple en lugar de introducir una nueva herramienta/tecnología, formar compañeros de trabajo e integrar el nueva herramienta en su sistema CI Pese los costos/beneficios cuidadosamente.

Cuestiones relacionadas