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

如何创建自定义注解自动生成Singleton类的样板代码?

自定义编译时注解实现单例类自动生成

需求说明

项目中需要创建大量单例类,希望通过自定义编译时注解,像Lombok的@Getter那样自动生成单例样板代码:包括私有静态final实例、私有构造方法、getInstance()静态方法。

比如只需要写:

@Singleton
public class AgeValidation {
    // 业务代码
}

编译后自动生成以下样板代码:

private static final AgeValidation instance = new AgeValidation();

private AgeValidation() { }

public static AgeValidation getInstance() {
    return instance;
}

实现步骤

1. 定义自定义注解@Singleton

创建注解类,指定作用目标为类,保留策略为编译时(SOURCE):

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 Singleton {
}

2. 编写注解处理器

继承AbstractProcessor,实现编译时解析@Singleton注解并生成代码的逻辑:

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.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

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

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(Singleton.class)) {
            if (element instanceof TypeElement) {
                TypeElement typeElement = (TypeElement) element;
                String className = typeElement.getSimpleName().toString();
                String packageName = processingEnv.getElementUtils().getPackageOf(typeElement).toString();

                try {
                    // 创建要生成的Java文件对象
                    JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(packageName + "." + className);
                    try (PrintWriter writer = new PrintWriter(sourceFile.openWriter())) {
                        // 写入包声明
                        writer.println("package " + packageName + ";");
                        writer.println();
                        // 写入类定义
                        writer.println("public class " + className + " {");
                        // 生成单例实例
                        writer.println("    private static final " + className + " instance = new " + className + "();");
                        writer.println();
                        // 生成私有构造方法
                        writer.println("    private " + className + "() { }");
                        writer.println();
                        // 生成getInstance方法
                        writer.println("    public static " + className + " getInstance() {");
                        writer.println("        return instance;");
                        writer.println("    }");
                        writer.println("}");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }
}

注意:上面的处理器是生成新的类文件,如果需要直接修改原有类(像Lombok那样修改字节码),建议使用JavaPoet或者ASM库来操作语法树或字节码,避免生成重复类。比如用JavaPoet可以更优雅地构建代码,还能保留原有类的成员。

3. 配置注解处理器

Maven配置

在pom.xml中添加注解处理器依赖和编译插件配置:

<dependencies>
    <!-- 注解API -->
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.2</version>
        <scope>provided</scope>
    </dependency>
    <!-- 可选:用JavaPoet简化代码生成 -->
    <dependency>
        <groupId>com.squareup</groupId>
        <artifactId>javapoet</artifactId>
        <version>1.13.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>8</source>
                <target>8</target>
                <annotationProcessors>
                    <annotationProcessor>com.yourpackage.SingletonProcessor</annotationProcessor>
                </annotationProcessors>
            </configuration>
        </plugin>
    </plugins>
</build>

自动注册处理器(可选)

使用@AutoService注解自动注册处理器,无需手动配置:

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

@AutoService(Processor.class)
@SupportedAnnotationTypes("com.yourpackage.Singleton")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SingletonProcessor extends AbstractProcessor {
    // 处理器逻辑...
}

需要添加AutoService依赖:

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

4. 使用示例

在你的类上添加@Singleton注解即可:

@Singleton
public class AgeValidation {
    // 这里写你的业务逻辑,编译时会自动生成单例相关代码
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:40:54