Gradle 插件任务反射扫描插件的项目 Class 文件而不是当前项目文件

Gradle Plugin Task Reflection Scans Plugin's Project Class Files Instead of Current Project Files

我创建了一个 Gradle 插件,它可以扫描我项目中的 class 文件并找出哪些文件有注释。

我让它工作并编译了它。现在,当我 运行 我项目中的任务时,它不会扫描我所在项目的 classes 和上面的 运行s 任务,而是扫描 class 插件项目本身的文件。我做错了什么?

final ClassLoader loader = Thread.currentThread().getContextClassLoader();
    try {
        ClassPath classpath = ClassPath.from(loader); // scans the class path used by classloader
        log.info("classPath = {}", classpath);
        for (ClassPath.ClassInfo classInfo : classpath.getTopLevelClassesRecursive(packageName)) {
            log.info("classInfo={}", classInfo);
            Class<?> clazz = classInfo.load();
            if (clazz.isAnnotationPresent(RestController.class)) {
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    doSomething(clazz, method);
                }
            }
        }
    } catch (IOException | NoSuchFieldException | IllegalAccessException ex) {
        String errorMsg = new StringBuilder("Unable to generate ").append(propertiesFileName).append(" file.").toString();
        log.error(errorMsg, ex);
        throw ex;
    }

这不能按您预期的方式工作:

  1. 默认情况下,您的项目 class 文件不会作为构建项目的一部分由 Gradle 加载。它们将通过编译生成,通过测试执行加载等...但通常不作为 Gradle 执行任务的一部分。
  2. 当您的插件接触到 classloader 时,它处于受管理的 Gradle 世界中,它有自己的 classloader 技巧。所以你必须了解使用了哪些技巧......但是给定 1,那仍然行不通。

鉴于您正在尝试的内容看起来很像 annotation processing,您应该调查处理您需求的方式。

在 Gradle 论坛中进行了大量挖掘,但我仍然遇到很多问题,但这是我能找到的最佳解决方案:

URL[] urls;
List<URL> listOfURL = new ArrayList<>();
SourceSetContainer ssc = getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets();
File classesDir = ssc.getByName("main").getOutput().getClassesDir();
listOfURL.add(classesDir.toURI().toURL());
urls = listOfURL.toArray(new URL[0]);
final ClassLoader loader = new URLClassLoader(urls);