java - 使用 gradle : howto? 构建 ServiceLoader 文件

标签 java groovy classloader gradle

我开始从一个著名的 Java 构建系统切换到 Gradle 来构建我的所有项目,仅仅两个小时后我就已经能够毫无问题地发布我的一个项目的新版本 - - 轻而易举。

但是现在我遇到了一个困难。简而言之,我需要复制 this Maven plugin 的功能它生成 ServiceLoader 所需的文件-启用服务。

简而言之:给定一个基类 foo.bar.MyClass,它会生成一个名为 META-INF/services/foo.bar.MyClass 的文件,其内容是当前项目中实现该接口(interface)/扩展该基类的类集。这样的文件看起来像:

com.mycompany.MyClassImpl
org.othercompany.MyClassImpl

为了做到这一点,它使用我不知道什么作为类加载器,加载 com.myCompany.MyClassImplClass 对象或其他对象,并检查是否这个类实现了想要的接口(interface)。

我正在尝试在 Gradle 中做同样的事情。几个小时的谷歌搜索让我找到了this plugin ,但在与作者稍微讨论后,该插件似乎能够合并此类文件,而不是创建它们。所以,我必须自己做...

而且我是 Gradle 和 Groovy 的真正初学者,这没有帮助!这是我当前的代码,链接到完整的 build.gradle here ;输出(我设法以某种方式获得;在干净的目录中不起作用)如下所示(请耐心等待......我使用 Java,我最终很高兴;Groovy 对我来说是全新的):

/*
 * TEST CODE
 */

final int CLASS_SUFFIX = ".class".length();
final URLClassLoader classLoader = this.class.classLoader;
// Where the classes are: OK
final File classesDir = sourceSets.main.output.classesDir;
final String basePath = classesDir.getCanonicalPath();

// Add them to the classloader: OK
classLoader.addURL(classesDir.toURI().toURL())

// Recurse over each file
classesDir.eachFileRecurse {
    // You "return" from a closure, you do not "continue"...
    if (!isPotentialClass(it))
        return;

    // Transform into a class name
    final String path = it.getAbsolutePath();
    final String name = path.substring(basePath.length() + 1);
    final String className = name.substring(0, name.length() - CLASS_SUFFIX)
        .replace('/', '.');

    // Try and load it
    try {
        classLoader.loadClass(className);
        println(className);
    } catch (NoClassDefFoundError ignored) {
        println("failed to load " + className + ": " + ignored);
    }
}

boolean isPotentialClass(final File file)
{
    return file.isFile() && file.name.endsWith(".class")
}

输出:

com.github.fge.msgsimple.InternalBundle
failed to load com.github.fge.msgsimple.bundle.MessageBundle: java.lang.NoClassDefFoundError: com/github/fge/Frozen
failed to load com.github.fge.msgsimple.bundle.MessageBundleBuilder: java.lang.NoClassDefFoundError: com/github/fge/Thawed
com.github.fge.msgsimple.bundle.PropertiesBundle$1
com.github.fge.msgsimple.bundle.PropertiesBundle
com.github.fge.msgsimple.provider.MessageSourceProvider
com.github.fge.msgsimple.provider.LoadingMessageSourceProvider$1
com.github.fge.msgsimple.provider.LoadingMessageSourceProvider$2
com.github.fge.msgsimple.provider.LoadingMessageSourceProvider$3
com.github.fge.msgsimple.provider.LoadingMessageSourceProvider$Builder
com.github.fge.msgsimple.provider.LoadingMessageSourceProvider
com.github.fge.msgsimple.provider.MessageSourceLoader
com.github.fge.msgsimple.provider.StaticMessageSourceProvider$Builder
com.github.fge.msgsimple.provider.StaticMessageSourceProvider$1
com.github.fge.msgsimple.provider.StaticMessageSourceProvider
com.github.fge.msgsimple.source.MessageSource
com.github.fge.msgsimple.source.MapMessageSource$Builder
com.github.fge.msgsimple.source.MapMessageSource$1
com.github.fge.msgsimple.source.MapMessageSource
com.github.fge.msgsimple.source.PropertiesMessageSource
com.github.fge.msgsimple.locale.LocaleUtils
com.github.fge.msgsimple.serviceloader.MessageBundleFactory
com.github.fge.msgsimple.serviceloader.MessageBundleProvider
:compileJava UP-TO-DATE

问题出在前两行:FrozenThawed位于不同的项目中,该项目位于编译类路径中,但不在我设法获取的类路径中到目前为止...因此,这些类甚至无法加载。

如何修改该代码以获得完整的编译类路径?这是我的第一个问题。第二个问题:当代码有效时,如何将其插入到构建过程中?

最佳答案

这里有一些提示:

  • 创建一个新的URLClassLoader ,而不是重用现有的。
  • 使用 sourceSets.main.compileClasspath 初始化类加载器(这是 Iterable<File> )而不是 classesDir .
  • 将代码转换为 Gradle 任务类。有关详细信息,请参阅 Gradle User Guide 中的“编写简单的任务类”。 .

理想情况下,您应该使用 ASM 之类的库来分析代码,而不是使用类加载器。为了避免由于类在内部引用不在编译类路径上的类而无法加载类的情况,您可能需要使用 sourceSets.main.runtimeClasspath 来初始化类加载器。相反。

关于java - 使用 gradle : howto? 构建 ServiceLoader 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17254495/

相关文章:

grails - grails “unable to resolve class groovy.util.FileNameFinder”

java - 如何将闭包从 groovy 导入到 java?

grails - 使用 "Getting Started with Grails"电子书进行集成测试时出现编译错误

java - 来自扩展类加载类的类转换异常

java - ImageView 可以是全局变量吗?

java - 在不加载类的情况下近似 class.getSimpleName() 的最佳方法是什么?

java - Java 类是如何加载的,我如何确定加载类的位置/时间/原因?

java - JSP 的类加载过程是怎样的?

java - 如何获取表中某一列的总和(对于特定的员工ID)并将其存储在另一个表的另一列中?

Java-8 - 从 Optional.of(String) 的开头替换 "?"字符