son - Procesamiento de anotación Java con manipulación de código fuente
para que sirven las anotaciones (3)
La API de procesamiento de anotación estándar no admite la modificación directa del código fuente. Sin embargo, algunos de los efectos de modificar el código fuente se pueden generar generando la superclase o la (s) subclase (s) del tipo anotado. La entrada del blog a continuación muestra un ejemplo de esta técnica:
He estado buscando una solución para el requisito a continuación:
- Los archivos de origen se escriben con Anotación personalizada en un método
- El cuerpo del método necesita una pequeña variación basada en la anotación.
- El archivo de origen no se debe cambiar, pero la entrada al compilador debe ser un archivo fuente modificado
He visto las API a continuación -
- javax.annotation.processing - Proceso de anotación.
- javax.lang.model. * - Modelo de lenguaje utilizado en el procesamiento de anotaciones y Compiler Tree API
- com.sun.source. * - Compiler Tree API.
Pensé en diseñar esto siguiendo lo siguiente:
- Escribir un procesador de anotación
- Genera el árbol compilador
- Edite el árbol del compilador en el tiempo de ejecución sin afectar el archivo fuente original
- Suministrar el árbol al compilador
Compiler Tree API parece estar prometiendo donde da acceso a com.sun.source.tree.MethodTree
Sin embargo, el compilador Tree API parece ser de solo lectura. No puedo entender cómo realizar los pasos 3 y 4
¿Hay alguna API para esto que pueda adoptar para realizar la tarea?
NOTA: Estoy buscando solo la técnica de manipulación del Código fuente. Sin manipulación del código de bytes de tiempo de ejecución / AOP
Medio ambiente: Java 6
Le sugiero que copie todo el código fuente en un directorio separado, modifique el código allí y compile a partir de la ruta temporal.
Puedes hacer esto como algo debajo que te permitirá lograr 3) y 4).
Ejemplo tomado del ejemplo del procesador de anotación Java
@SupportedAnnotationTypes( "com.javacodegeeks.advanced.processor.Immutable" )
@SupportedSourceVersion( SourceVersion.RELEASE_7 )
public class SimpleAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(final Set< ? extends TypeElement > annotations,
final RoundEnvironment roundEnv) {
for( final Element element: roundEnv.getElementsAnnotatedWith( Immutable.class ) ) {
if( element instanceof TypeElement ) {
final TypeElement typeElement = ( TypeElement )element;
for( final Element eclosedElement: typeElement.getEnclosedElements() ) {
if( eclosedElement instanceof VariableElement ) {
final VariableElement variableElement = ( VariableElement )eclosedElement;
if( !variableElement.getModifiers().contains( Modifier.FINAL ) ) {
processingEnv.getMessager().printMessage( Diagnostic.Kind.ERROR,
String.format( "Class ''%s'' is annotated as @Immutable,
but field ''%s'' is not declared as final",
typeElement.getSimpleName(), variableElement.getSimpleName()
)
);
}
}
}
}
// Claiming that annotations have been processed by this processor
return true;
}
}
Otra forma de usar projectlombok con controlador personalizado.
Ejemplo incorporado en el controlador de GitHub Project Lombok. Esta anotación agrega bloque try catch
public class SneakyThrowsExample implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
@SneakyThrows
public void run() {
throw new Throwable();
}
}
Esto se procesa para
public String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Lombok.sneakyThrow(e);
}
}
public void run() {
try {
throw new Throwable();
} catch (Throwable t) {
throw Lombok.sneakyThrow(t);
}
}
Puede encontrar el código de Handler en el mismo sitio de Github / lombok.