20

在我的 build.gradle 文件中,我需要添加以下行:

shadowJar {
    mergeServiceFiles()
}

否则 jar 无法正常运行。我想知道这条线到底是做什么的?我在 Eclipse Luna 中使用 Gradle 插件。我在一个依赖于另一个 Java 项目的 Java 项目上创建了 jar。

4

2 回答 2

10

mergeServiceFiles在这里完全声明,其实现如下:

/**
 * Syntactic sugar for merging service files in JARs
 * @return
 */
public ShadowJar mergeServiceFiles() {
    try {
        transform(ServiceFileTransformer.class);
    } catch (IllegalAccessException e) {
    } catch (InstantiationException e) {
    }
    return this;
}

如您所见,它使用了此处ServiceFileTransfomer定义的内容。从它的文档:

从 org.apache.maven.plugins.shade.resource.ServiceResourceTransformer.java 修改

将 META-INF/services 资源中的条目附加到单个资源中的资源转换器。例如,如果有多个 META-INF/services/org.apache.maven.project.ProjectBuilder 资源分布在许多 JAR 中,则各个条目将全部连接到单个 META-INF/services/org.apache.maven.project .ProjectBuilder 资源打包到着色过程生成的结果 JAR 中。

于 2015-10-02T07:19:47.960 回答
1

TL;DR - 它合并 META-INF/services 文件夹中的服务文件。

长答案

一些库(例如 Micronaut)在文件夹中创建了一些服务文件META-INF/services。这些文件可以包含在运行时有用的任何信息。在 Micronaut 框架的情况下,它会创建一个文件,该文件在io.micronaut.inject.BeanDefinitionReference名为META-INF/services.

通常,如果您只有一个应用程序,即使没有mergeServiceFiles(). 但是,如果您将两个 micronaut 项目捆绑到一个 jar 中(例如,一个lib带有一些实用程序的 micronautapp项目和一个带有核心业务逻辑的 micronaut 项目),您将拥有两个io.micronaut.inject.BeanDefinitionReference. 每个都将包含它自己的项目的bean。

如果您不使用mergeServiceFiles(),其中一个BeanDefinitionReference文件将被另一个文件覆盖。在这种情况下,你会得到一个运行时异常BeanNotInstantiated或类似的东西。

使用mergeServiceFiles()合并(或在这种情况下连接)BeanDefinitionReference两个项目的文件,以便在运行时获得所有定义的 bean。

更多详细信息可以在此处的 gradle 论坛主题中找到。

于 2021-04-07T13:17:16.953 回答