在我的 build.gradle 文件中,我需要添加以下行:
shadowJar {
mergeServiceFiles()
}
否则 jar 无法正常运行。我想知道这条线到底是做什么的?我在 Eclipse Luna 中使用 Gradle 插件。我在一个依赖于另一个 Java 项目的 Java 项目上创建了 jar。
在我的 build.gradle 文件中,我需要添加以下行:
shadowJar {
mergeServiceFiles()
}
否则 jar 无法正常运行。我想知道这条线到底是做什么的?我在 Eclipse Luna 中使用 Gradle 插件。我在一个依赖于另一个 Java 项目的 Java 项目上创建了 jar。
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 中。
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 论坛主题中找到。