java注解的处理器

Java注解处理器(Annotation Processor)是Java编译器的一部分,它能够在编译期间处理注解,并根据注解生成新的源代码或字节码。注解处理器在Java编译过程中运行,可以生成额外的类、接口、方法或字段,从而实现代码生成和其他编译时任务。

Java注解处理器的基本概念

Java注解处理器(Annotation Processor)是一种特殊的编译器插件,它允许开发者在编译期间处理注解,并根据注解生成新的源代码或字节码。注解处理器通常用于生成额外的类、接口、方法或字段,以实现代码生成和其他编译时任务。

注解处理器的工作流程

  1. 编写注解处理器 :编写一个实现了javax.annotation.processing.Processor接口的类。
  2. 注册注解处理器:通过命令行或配置文件告诉Java编译器(javac)使用你的注解处理器。
  3. 处理注解:在编译期间,注解处理器根据注解生成新的源代码或字节码。

注解处理器的基本步骤

1. 创建注解

首先定义一个注解,用于标记需要处理的类或方法。

复制代码
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface GenerateBean {
    String author() default "Unknown";
}
2. 编写注解处理器

实现javax.annotation.processing.Processor接口,并重写process方法。

复制代码
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;

@SupportedAnnotationTypes("com.example.GenerateBean")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class BeanProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
            for (Element element : annotatedElements) {
                if (element instanceof TypeElement) {
                    TypeElement typeElement = (TypeElement) element;
                    generateBeanClass(typeElement);
                }
            }
        }
        return true;
    }

    private void generateBeanClass(TypeElement typeElement) {
        String packageName = processingEnv.getElementUtils().getPackageOf(typeElement).getQualifiedName().toString();
        String className = typeElement.getSimpleName().toString();
        String qualifiedClassName = packageName + "." + className;
        String author = typeElement.getAnnotation(GenerateBean.class).author();

        String generatedClassName = qualifiedClassName + "Bean";
        String generatedCode = String.format(
                "package %s;\n" +
                "public class %s {\n" +
                "    private String name = \"%s\";\n" +
                "    public String getName() { return name; }\n" +
                "}", packageName, generatedClassName, author);

        try (Writer writer = processingEnv.getFiler().createSourceFile(generatedClassName).openWriter()) {
            writer.write(generatedCode);
        } catch (IOException e) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Error generating bean class: " + e.getMessage());
        }
    }
}
3. 注册注解处理器

通过命令行或配置文件告诉Java编译器(javac)使用你的注解处理器。

通过命令行注册
复制代码
javac -processorpath path/to/your/processor.jar -processor com.example.BeanProcessor YourSourceFiles.java
通过processor文件注册

创建一个名为META-INF/services/javax.annotation.processing.Processor的文件,并在其中指定处理器的全限定名:

复制代码
com.example.BeanProcessor

然后将这个文件放入META-INF/services目录下。

示例代码

1. 创建注解
复制代码
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface GenerateBean {
    String author() default "Unknown";
}
2. 编写注解处理器
复制代码
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;

@SupportedAnnotationTypes("com.example.GenerateBean")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class BeanProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
            for (Element element : annotatedElements) {
                if (element instanceof TypeElement) {
                    TypeElement typeElement = (TypeElement) element;
                    generateBeanClass(typeElement);
                }
            }
        }
        return true;
    }

    private void generateBeanClass(TypeElement typeElement) {
        String packageName = processingEnv.getElementUtils().getPackageOf(typeElement).getQualifiedName().toString();
        String className = typeElement.getSimpleName().toString();
        String qualifiedClassName = packageName + "." + className;
        String author = typeElement.getAnnotation(GenerateBean.class).author();

        String generatedClassName = qualifiedClassName + "Bean";
        String generatedCode = String.format(
                "package %s;\n" +
                "public class %s {\n" +
                "    private String name = \"%s\";\n" +
                "    public String getName() { return name; }\n" +
                "}", packageName, generatedClassName, author);

        try (Writer writer = processingEnv.getFiler().createSourceFile(generatedClassName).openWriter()) {
            writer.write(generatedCode);
        } catch (IOException e) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Error generating bean class: " + e.getMessage());
        }
    }
}
3. 使用注解
复制代码
package com.example;

@GenerateBean(author = "John Doe")
public class Person {
    // 类定义
}
4. 注册注解处理器
通过命令行注册
复制代码
javac -processorpath path/to/your/processor.jar -processor com.example.BeanProcessor Person.java
通过processor文件注册

创建一个名为META-INF/services/javax.annotation.processing.Processor的文件,并在其中指定处理器的全限定名:

复制代码
com.example.BeanProcessor

然后将这个文件放入META-INF/services目录下。

运行结果

当编译Person.java时,注解处理器会在同一包下生成一个新的PersonBean.java文件:

复制代码
package com.example;

public class PersonBean {
    private String name = "John Doe";

    public String getName() {
        return name;
    }
}

总结

Java注解处理器(Annotation Processor)是Java编译器的一部分,能够在编译期间处理注解,并根据注解生成新的源代码或字节码。通过使用注解处理器,可以实现代码生成和其他编译时任务,从而简化代码编写和维护工作。

掌握Java注解处理器的基本概念和使用方法后,可以更好地利用注解处理器来编写灵活和动态的应用程序。

相关推荐
哦虎!1 小时前
【JavaEE】网络初识
java
for_ever_love__1 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
我是人✓2 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
欣栀♡2 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室3 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项3 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs
Wang's Blog3 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务提供者
java·dubbo·交友
秋饼3 小时前
Spring AI 2.0 结构化输出企业级实战:从 BeanOutputConverter 源码到生产级解析容错
java·ai·技术分享·后端开发
摇滚侠3 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y3 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python