You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似Lombok @Getter的自定义@MyGetter编译期注解?

实现自定义@MyGetter注解生成带条件判断的Getter

一、定义@MyGetter注解

首先创建注解类,指定其仅在编译阶段生效,作用目标为类:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

二、编写注解处理器(核心逻辑)

创建继承AbstractProcessor的处理器类,负责扫描带@MyGetter的类,为私有String字段生成带条件判断的Getter方法:

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.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;

@SupportedAnnotationTypes("com.yourpackage.MyGetter") // 替换为你的注解全类名
@SupportedSourceVersion(SourceVersion.RELEASE_8) // 根据JDK版本调整
public class MyGetterProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // 遍历所有标注@MyGetter的类
        for (Element element : roundEnv.getElementsAnnotatedWith(MyGetter.class)) {
            if (!element.getKind().isClass()) continue;

            TypeElement classElement = (TypeElement) element;
            String className = classElement.getSimpleName().toString();
            String packageName = processingEnv.getElementUtils().getPackageOf(classElement).toString();

            try {
                // 创建目标类的Java文件对象
                JavaFileObject file = processingEnv.getFiler().createSourceFile(packageName + "." + className);
                try (Writer writer = file.openWriter()) {
                    // 写入包声明与类注解
                    writer.write("package " + packageName + ";\n\n");
                    writer.write("@MyGetter\n");
                    writer.write("public class " + className + " {\n\n");

                    // 遍历类内所有元素,原样保留非目标字段/方法,生成目标Getter
                    for (Element enclosedElement : classElement.getEnclosedElements()) {
                        if (enclosedElement.getKind().isField()) {
                            VariableElement field = (VariableElement) enclosedElement;
                            // 仅处理私有String类型字段
                            if (field.getModifiers().contains(javax.lang.model.element.Modifier.PRIVATE)
                                    && field.asType().toString().equals("java.lang.String")) {

                                String fieldName = field.getSimpleName().toString();
                                // 生成Getter方法名(小驼峰转大驼峰)
                                String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

                                // 写入原字段声明
                                writer.write("    private String " + fieldName + ";\n\n");
                                // 写入带条件判断的Getter方法
                                writer.write("    public String " + getterName + "() {\n");
                                writer.write("        if (isHexString()) {\n");
                                writer.write("            // 替换为你的实际处理逻辑\n");
                                writer.write("            return \"processed_\" + " + fieldName + ";\n");
                                writer.write("        }\n");
                                writer.write("        return " + fieldName + ";\n");
                                writer.write("    }\n\n");
                            } else {
                                // 非目标字段原样写入
                                writer.write("    " + enclosedElement + ";\n\n");
                            }
                        } else if (enclosedElement.getKind().isMethod()) {
                            // 原有方法(如isHexString)原样保留
                            writer.write("    " + enclosedElement + "\n\n");
                        }
                    }

                    writer.write("}\n");
                }
            } catch (IOException e) {
                processingEnv.getMessager().printError("生成Getter失败: " + e.getMessage());
            }
        }
        return true;
    }
}

三、注册注解处理器

让编译器识别这个处理器,有两种常用方式:

方式1:手动配置META-INF

在项目src/main/resources/META-INF/services目录下创建文件javax.annotation.processing.Processor,内容为处理器全类名:

com.yourpackage.MyGetterProcessor

方式2:使用AutoService自动注册(推荐)

添加Maven依赖:

<dependency>
    <groupId>com.google.auto.service</groupId>
    <artifactId>auto-service</artifactId>
    <version>1.0.1</version>
    <scope>provided</scope>
</dependency>

然后在处理器类上添加注解:

import com.google.auto.service.AutoService;
import javax.annotation.processing.Processor;

@AutoService(Processor.class)
@SupportedAnnotationTypes("com.yourpackage.MyGetter")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyGetterProcessor extends AbstractProcessor {
    // 原有代码不变
}

四、测试使用

创建测试类(需包含isHexString判断方法):

@MyGetter
public class AnyClass {
    private String fieldVariable;

    // 自定义的十六进制判断方法
    private boolean isHexString() {
        return fieldVariable != null && fieldVariable.matches("[0-9A-Fa-f]+");
    }
}

编译后会自动生成包含目标Getter的类文件,效果如下:

package com.yourpackage;

@MyGetter
public class AnyClass {

    private String fieldVariable;

    private boolean isHexString() {
        return fieldVariable != null && fieldVariable.matches("[0-9A-Fa-f]+");
    }

    public String getFieldVariable() {
        if (isHexString()) {
            // 替换为你的实际处理逻辑
            return "processed_" + fieldVariable;
        }
        return fieldVariable;
    }

}

注意事项

  • 确保处理器能正确保留类中原有的非目标元素(如其他字段、方法)。
  • isHexString方法需在目标类中存在,若需要自动生成该方法,可扩展处理器逻辑添加对应代码。
  • 字段名转驼峰的逻辑可根据需求优化(比如处理字段名以多个大写字母开头的场景)。

内容的提问来源于stack exchange,提问作者TomYOON

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:36:24