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

如何在注解处理器中获取所有实现指定接口的类?

在注解处理器中获取所有实现指定接口的类并生成Map

核心思路:基于编译期扫描与代码生成

注解处理器运行在编译阶段,可直接获取当前编译上下文内的所有类元素,结合SPI式的资源收集处理跨模块依赖类,最终直接生成Map的初始化代码(避免运行时反射开销)。


  • 编译期扫描当前上下文的实现类
    通过ProcessingEnvironment提供的工具类,遍历所有编译中的TypeElement,判断是否实现目标接口:

    // 获取目标接口的TypeElement
    TypeElement targetInterface = processingEnv.getElementUtils().getTypeElement("com.your.package.TargetInterface");
    TypeMirror targetType = targetInterface.asType();
    Types typeUtils = processingEnv.getTypeUtils();
    
    // 遍历所有根元素(可通过RoundEnvironment获取)
    for (Element element : roundEnv.getRootElements()) {
        if (element.getKind() == ElementKind.CLASS) {
            TypeElement classElement = (TypeElement) element;
            // 判断当前类是否实现了目标接口
            if (typeUtils.isAssignable(classElement.asType(), targetType)) {
                // 记录该类的全限定名
                String className = classElement.getQualifiedName().toString();
            }
        }
    }
    
  • 处理依赖jar包中的实现类
    若目标类在依赖模块或jar中,编译期无法直接扫描,可通过SPI机制收集:

    1. 在每个模块的注解处理器中,将发现的实现类全限定名写入META-INF/services/com.your.package.TargetInterface文件。
    2. 最终生成Map时,读取所有该路径下的文件,收集所有实现类名。
  • 直接生成Map初始化代码
    推荐在编译期生成Map的Java代码,无需运行时反射:
    利用Filer创建新的Java类,写入Map初始化逻辑:

    // 创建生成类的文件对象
    JavaFileObject file = processingEnv.getFiler().createSourceFile("com.your.package.GeneratedMapHolder");
    try (Writer writer = file.openWriter()) {
        writer.write("package com.your.package;\n");
        writer.write("import java.util.HashMap;\n");
        writer.write("import java.util.Map;\n");
        writer.write("public class GeneratedMapHolder {\n");
        writer.write("    public static final Map<Class<?>, Object> IMPLEMENT_MAP = new HashMap<>();\n");
        writer.write("    static {\n");
        // 遍历收集到的实现类,逐个添加到Map中
        for (String className : collectedClassNames) {
            writer.write(String.format("        IMPLEMENT_MAP.put(%s.class, new %s());\n", className, className));
        }
        writer.write("    }\n");
        writer.write("}\n");
    }
    
  • 关键注意事项

    • 必须在META-INF/services/javax.annotation.processing.Processor文件中注册你的注解处理器类,确保编译时被调用。
    • 若处理Kotlin类,需配合KAPT工具,确保能正确识别Kotlin类元素。
    • 通过@SupportedAnnotationTypes指定处理器关注的注解,缩小扫描范围提升性能。

内容的提问来源于stack exchange,提问作者kylie.zoltan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:01:17