You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Gradle Shadow插件重定位SPI服务并保留服务文件名?

使用Gradle Shadow插件重定位SPI并保留原服务文件名

不用额外做解压-修改-重打包的步骤,直接通过Shadow插件的自定义Transform机制就能实现需求。核心逻辑是:

  • 正常配置类的重定位规则
  • 对META-INF/services下的服务文件,保留原文件名,但替换文件内容里的类全限定名为重定位后的名称

以下是完整的Gradle Groovy DSL配置示例:

plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '8.1.1'
}

repositories {
    mavenCentral()
}

shadowJar {
    // 配置类重定位:将some包下的类全部移到relocated包
    relocate 'some', 'relocated'

    // 添加自定义Transform处理SPI服务文件
    transform(com.github.jengelman.gradle.plugins.shadow.transformers.Transformer) {
        // 只处理META-INF/services目录下的文件
        @Override
        boolean canTransformResource(FileTreeElement element) {
            return element.path.startsWith('META-INF/services/')
        }

        @Override
        void transform(TransformerContext context) {
            def input = context.inputStream.text
            // 替换原类名为重定位后的类名
            def outputContent = input.replaceAll('some\\.Service', 'relocated\\.Service')
            // 写入修改后的内容,同时保留原文件路径
            context.outputStream.write(outputContent.getBytes())
        }

        @Override
        boolean hasTransformedResource() {
            return true
        }
    }

    // 确保不排除META-INF/services下的文件,让Transform能处理它们
    exclude { false }
}

关键细节说明:

  1. 类重定位规则:relocate 'some', 'relocated'会自动将所有some包下的.class文件移动到relocated路径下,无需手动处理类文件。
  2. 自定义Transform:
    • canTransformResource方法过滤出需要处理的SPI服务文件
    • transform方法读取文件内容,替换原类全限定名,再写入输出流,同时通过context.path保留原文件路径
  3. 排除策略:不要用排除规则跳过服务文件,否则Transform无法对其进行内容修改。

执行./gradlew shadowJar后,生成的JAR会完全符合需求:

  • 原/java/some/Service.class被重定位为/relocated/Service.class
  • 服务文件路径仍为/META-INF/services/some.Service,但文件内容已替换为relocated.Service

内容的提问来源于stack exchange,提问作者lattitudesto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 23:47:26