java - 选择具有给定注释的类

标签 java ant annotations

我有一堆 java 类的源文件。我想找到那些由给定注释类注释的类。这些类的名称应写入服务提供者列表文件。

有什么机器可以帮助我完成这项任务吗?或者我必须自己从头开始实现这个?

如果我必须自己做这件事,我可以想到几种方法。

  1. 用 Java 编写 Ant 任务。让它创建一个 ClassLoader使用合适的(可能是可配置的)类路径。使用该加载器(尝试)加载与输入文件匹配的类,以便检查它们的注释。需要在运行时保留注释,并完全初始化所有涉及的类及其依赖项。

  2. 使用 javap 检查类。因为我不知道 javap 的编程接口(interface)(你是吗?),这可能意味着迭代文件并为每个文件运行一个新进程,然后以合适的方式调整创建的输出。也许是<scriptdef> -ed 任务可以用于此目的。这将与类文件注释保留一起使用,并且不需要初始化。

  3. 使用注释处理器在编译时收集信息。这应该能够与仅保留源代码一起使用。但我没有编写或使用注释编译器的经验,所以我不确定这是否有效,并且需要大量研究来弄清楚一些细节。特别是如何激活任务以供 ant 使用( Java 6 annotation processing configuration with Ant 对此提供了一些指示, What is the default annotation processors discovery process? 也是如此)以及何时创建输出文件(在每一轮中,或仅在最后一轮中)。

您认为其中哪一个最有可能成功?您能否建议其中之一的代码示例,它可能接近我想要的并且我可以适当调整?

最佳答案

在 Thomas 评论的鼓励下,我尝试了方法 3,并让以下注释处理器工作得相当好:

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
import javax.tools.StandardLocation;

@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class AnnotationServiceProcessor extends AbstractProcessor {

    // Map name of the annotation to name of the corresponding service interface
    private static Map<String, String> annotationToServiceMap = new HashMap<>();

    static {
        // Adapt this to your use, or make it configurable somehow
        annotationToServiceMap.put("Annotation1", "Service1");
        annotationToServiceMap.put("Annotation2", "Service2");
    }

    @Override public Set<String> getSupportedAnnotationTypes() {
        return annotationToServiceMap.keySet();
    }

    // Map name of the annotation to list of names
    // of the classes which carry that annotation
    private Map<String, List<String>> classLists;

    @Override public void init(ProcessingEnvironment env) {
        super.init(env);
        classLists = new HashMap<>();
        for (String ann: getSupportedAnnotationTypes())
            classLists.put(ann, new ArrayList<String>());
    }

    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment env) {
        for (TypeElement ann: annotations) {
            List<String> classes =
                classLists.get(ann.getQualifiedName().toString());
            for (Element elt: env.getElementsAnnotatedWith(ann)) {
                QualifiedNameable qn = (QualifiedNameable)elt;
                classes.add(qn.getQualifiedName().toString());
            }
        }
        if (env.processingOver()) { // Only write results at the end
            for (String ann: getSupportedAnnotationTypes()) {
                try {
                    write(ann, classLists.get(ann));
                } catch (IOException e) {
                    throw new RuntimeException(e); // UGLY!
                }
            }
        }
        return true;
    }

    // Write the service file for each annotation we found
    private void write(String ann, List<String> classes) throws IOException {
        if (classes.isEmpty())
            return;
        String service = annotationToServiceMap.get(ann);
        Writer w = processingEnv.getFiler()
            .createResource(StandardLocation.CLASS_OUTPUT,
                            "", "META-INF/services/" + service)
            .openWriter();
        classes.sort(null); // Make the processing order irrelevant
        for (String cls: classes) {
            w.write(cls);
            w.write('\n');
        }
        w.close();
    }

}

到目前为止,我已经使用 <compilerarg> 将其连接到 ant来自https://stackoverflow.com/a/3644624/1468366 。我会尝试更好的方法,如果成功,我将编辑这篇文章以包含一些 Ant 片段。

关于java - 选择具有给定注释的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35556410/

相关文章:

ant - Ant 的宏定义的默认元素?

ant - 你如何让 *ant* 不打印出 javac 警告?

java - 尝试引用 Jar 文件时 Eclipse 出现不支持的 Major.minor 版本 51.0 错误

java - Dropwizard + Jersey : "Not inside a request scope" when creating custom annotation

java - Jenkins 在后台启动应用程序

java - JSF 中文件浏览的替代方案是什么?

java - 如何从非委托(delegate)类在 camunda 中设置新变量

java - 整数加密 RC4 算法

java - 如何删除javax注释警告

java - 将动态参数传递给注释