¿Qué hace el procesador de anotaciones?

Un procesador de sondeo en anotaciones

    Hay un complemento muy útil en el proyecto, llamado lombok. Proporciona algunas anotaciones simples, que se pueden usar para generar javabean y algunos métodos getter / setter, lo que mejora la eficiencia del desarrollo y ahorra tiempo de desarrollo.
Hoy llegaremos Eche un vistazo al método que utiliza lombok para realizar esta operación. De hecho, lombok utiliza el procesador de anotaciones, que es una nueva función agregada en jdk1.5. Como @Getter es solo una anotación, y su parte real de procesamiento
está en el procesador de anotaciones. Realizado en el interior Enlace de referencia oficial .

Introducción de antecedentes

    El nombre completo del procesador de anotaciones es en realidad Pluggable Annotation Processing API, un procesador de anotaciones enchufable. Es una implementación de la propuesta JSR269. Para obtener más detalles, puede ver el contenido en el enlace , el enlace JSR269 .
¿Cómo funciona? Puede consultar la siguiente figura:

1. parse and enter: parse and enter, el compilador java analizará el código fuente para generar un AST (Abstract Syntax Analysis Tree)
en esta etapa 2.Procesamiento de anotaciones: la etapa del procesador de anotaciones, el procesador de anotaciones se llamará en este momento y el código se puede verificar en este momento , Generar archivos nuevos, etc. (puede recorrer el primer paso después del procesamiento)
3.analizar y generar: analizar y generar, en este momento, después de completar los dos primeros pasos, generar código de bytes (comprender el azúcar en esta etapa, como el borrado de tipos)
En realidad, estos son solo para dar a todos una impresión superficial de cómo se implementa.

práctica

    Después de leer la información anterior, debería tener una impresión general en su cerebro. Ahora escribamos un ejemplo simple y practiquemos.
Para usar el procesador de anotaciones se requieren dos pasos:
1. Personalizar una anotación
2. Heredar AbstractProcessor E implementar el método de proceso

Escribamos un ejemplo muy simple, que es agregar @InterfaceAnnotation a una clase y generar una clase de interfaz de "I" + nombre de clase al compilar. En
primer lugar, he definido dos moudles, uno para escribir Anotaciones y controladores, el otro se usa para llamar anotaciones.

Paso 1: personalizar una anotación

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface InterfaceAnnotation {
}

1. @ Target: indica en qué se usa esta anotación, aquí ElementType.TYPE se refiere al uso de la anotación en la clase
2. @ Retention: indica la etapa de retención, aquí RetentionPolicy.SOURCE es la etapa del código fuente, compilar No existe tal anotación en la última clase

Paso 2: heredar AbstractProcessor e implementar el método de proceso

@SupportedAnnotationTypes(value = {"com.example.processor.InterfaceAnnotation"})
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
public class InterfaceProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Messager messager = processingEnv.getMessager();
        messager.printMessage(Diagnostic.Kind.NOTE, "进入到InterfaceProcessor中了~~~");
        // 将带有InterfaceProcessor的类给找出来
        Set<? extends Element> clazz = roundEnv.getElementsAnnotatedWith(InterfaceAnnotation.class);
        clazz.forEach(item -> {
            // 生成一个 I + 类名的接口类
            String className = item.getSimpleName().toString();
            className = "I" + className.substring(0, 1) + className.substring(1);
            TypeSpec typeSpec = TypeSpec.interfaceBuilder(className).addModifiers(Modifier.PUBLIC).build();

            try {
                // 生成java文件
                JavaFile.builder("com.example.processor", typeSpec).build().writeTo(new File("./src/main/java/"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        return true;
    }
}

1. @ SupportedAnnotationTypes: indica qué anotaciones entrarán en vigor esta clase de procesador
2. @ SupportedSourceVersion: indica la versión de Java admitida
3.annotations: Las anotaciones requeridas son las anotaciones correspondientes a @SupportedAnnotationTypes
4.roundEnv: Almacena las rondas actual y anterior Información del entorno de procesamiento
5. TypeSpec puede ser un poco ininteligible, es una clase en javaPoet, javaPoet es un complemento de terceros utilizado por java para generar archivos java es muy útil, por lo que esta clase se usa aquí Para generar archivos java, de
hecho , los archivos java también se pueden generar usando PrintWriter y otros flujos de entrada y salida que vienen con java. Hay muchas formas de generar archivos. El enlace a javaPoet . La guía de uso de javaPoet .
6. Messager se usa para imprimir información de salida, System .out.println también es posible;
7. Si el proceso devuelve verdadero, el procesador de anotaciones subsiguiente no procesará esta anotación nuevamente, si es falsa, en la siguiente ronda de procesamiento, otros procesadores de anotaciones también procesarán la anotación modificada.

Después de escribir, debe especificar el procesador aquí, META-INF / services / javax.annotation.processing.Processor y escribir com.example.processor.InterfaceProcessor. Si no sabe qué es esto, puede leer mi otro blog (Strength Promocionar XD) ¿Qué es SPI?
Estamos compilando el procesador de anotaciones y la configuración del complemento en maven:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <!-- 不加这一句编译会报找不到processor的异常-->
              <compilerArgument>-proc:none</compilerArgument>
        </configuration>
</plugin>

La estructura del directorio en este momento es así:

.
├── HELP.md
├── pom.xml
├── processor.iml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── processor
        │               ├── InterfaceAnnotation.java
        │               └── InterfaceProcessor.java
        └── resources
            └── META-INF
                └── services
                    └── javax.annotation.processing.Processor

Entonces mvn clean install.

Paso 3: usa anotaciones

Antes de usarlo, si el procesador de anotaciones está compilado, introduzca el paquete jar del procesador de anotaciones.
Agregue @InterfaceAnnotation a la clase de prueba

@InterfaceAnnotation
public class TestProcessor {
}

maven especifica el procesador de anotaciones utilizado durante la compilación.

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <encoding>UTF-8</encoding>
              <annotationProcessors>
                  <annotationProcessor>
                        com.example.processor.InterfaceProcessor
                  </annotationProcessor>
              </annotationProcessors>
        </configuration>
</plugin>

La estructura del directorio en este momento es

.
├── HELP.md
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── example
│       │           └── test
│       │               └── TestProcessor.java
│       └── resources
└── test.iml

Luego se compila mvn, se genera el archivo java y la estructura del directorio es:

.
├── HELP.md
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── example
│       │           ├── processor
│       │           │   └── ITestProcessor.java  // 这里就是生成的java文件
│       │           └── test
│       │               └── TestProcessor.java
│       └── resources
├── target
│   ├── classes
│   │   └── com
│   │       └── example
│   │           └── test
│   │               └── TestProcessor.class
│   ├── generated-sources
│   │   └── annotations
│   └── maven-status
│       └── maven-compiler-plugin
│           └── compile
│               └── default-compile
│                   ├── createdFiles.lst
│                   └── inputFiles.lst
└── test.iml

Vea el archivo java generado y listo ~

para resumir:

1.El procesador de anotaciones Java se puede usar en muchos lugares, aplicaciones prácticas como lombok, generación de fragmentos de Android, etc., usar solo una anotación puede ahorrar mucho código y mejorar la eficiencia;
2. Este artículo solo enumera un ejemplo muy simple, muchos Las API en el procesador de anotaciones no se utilizan. Los lectores interesados ​​pueden estudiar por sí mismos, y hay API relacionadas con árboles de sintaxis abstracta;
3. Los procesadores de anotaciones se pueden utilizar para generar nuevas clases para completar ciertas funciones, pero no pueden ser directamente Modifica la clase actual.

Materiales de referencia:

1. https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html
2. https://jcp.org/aboutJava/communityprocess/final/jsr269/index.html
3. https://github.com/square/javapoet
4. https://www.cnblogs.com/throwable/p/9139908.html
5. http://notatube.blogspot.com/2010/11/project- lombok-trick-explicit.html (介绍 处理 过程)
6. https://www.baeldung.com/java-annotation-processing-builder
7. http://hannesdorfmann.com/annotation-processing/annotationprocessing101

Supongo que te gusta

Origin blog.csdn.net/sc9018181134/article/details/95911937
Recomendado
Clasificación