Shadow Plugin Gradle:mergeServiceFiles()有什么作用?

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

shadowJar {
    mergeServiceFiles()
}

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


答案 1

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/服务资源中的条目追加到单个资源中。例如,如果有多个 META-INF/services/org.apache.maven.project.ProjectBuilder 资源分布在许多 JAR 中,则各个条目将全部串联到单个 META-INF/services/org.apache.maven.project.Project.ProjectBuilder 资源中,该资源打包到由着色过程生成的结果 JAR 中。


答案 2

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

长答案

一些库(例如Micronaut)在文件夹中创建一些服务文件。这些文件可以包含运行时有用的任何信息。对于 Micronaut 框架,它会创建一个文件,该文件在名为 的文件中列出 Bean 引用(或实例化的 Bean)。META-INF/servicesio.micronaut.inject.BeanDefinitionReferenceMETA-INF/services

通常,如果您只有一个应用程序,即使没有,它也可以正常工作。但是,如果您将两个micronaut项目捆绑到一个jar中(例如,具有一些utils的micronaut项目和具有核心业务逻辑的micronaut项目),您将有两个。每个都将包含其自己项目的豆子。mergeServiceFiles()libappio.micronaut.inject.BeanDefinitionReference

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

使用合并(在本例中为连接)两个项目的文件,以便在运行时获得定义的所有 Bean。mergeServiceFiles()BeanDefinitionReference

有关更多详细信息,请参阅此处的 gradle 论坛主题。


推荐