如何在sbt中实现类似Shading效果处理含相同类的双依赖导入?
无需构建Uber Jar的SBT依赖类隔离方案(处理重复类冲突)
Hey there! 我完全懂你现在的困扰——两个同组的依赖commons-avro和commons-avro-enum带着完全相同的类,想要实现类似Shading的隔离效果,但又不想打包成Uber Jar。下面给你几个在SBT环境下就能落地的替代方案:
方案1:精准排除冗余依赖(适用于重复类可替代的场景)
如果其中一个库的重复类是另一个的子集,或者你明确知道只需要某一个版本的实现,可以直接在依赖声明里排除冲突的模块,或者强制统一依赖版本:
排除指定依赖模块
libraryDependencies ++= Seq( "com.company.avro" %% "commons-avro" % "1.1.34", // 排除commons-avro-enum中自带的commons-avro依赖 "com.company.avro" %% "commons-avro-enum" % "1.1.34" exclude ("com.company.avro", "commons-avro_2.13") )
强制统一依赖版本
如果两个库的同版本类逻辑一致,用dependencyOverrides强制项目只使用指定版本的类:
dependencyOverrides += "com.company.avro" %% "commons-avro" % "1.1.34"
注意:这个方案只适合重复类逻辑一致的情况,如果两个库的同名类有不同实现,用这个方法会导致功能异常。
方案2:用SBT Shader插件做编译时类重命名(真正的类隔离)
不想打Uber Jar也能做Shading!sbt-shader-plugin可以在编译阶段就对指定依赖的类进行包路径重命名,实现类隔离,步骤如下:
- 先在
project/plugins.sbt中添加插件:
addSbtPlugin("com.eed3si9n" % "sbt-shader-plugin" % "0.1.1")
- 然后在
build.sbt中配置Shading规则:
enablePlugins(ShaderPlugin) // 将commons-avro-enum中的com.company.avro包重命名为shaded.com.company.avro shadeRules += ShadeRule.rename("com.company.avro.**" -> "shaded.com.company.avro.@1") .inLibrary("com.company.avro" %% "commons-avro-enum" % "1.1.34") .inProject()
配置完成后,commons-avro-enum里的所有类都会被移到shaded.com.company.avro路径下,和commons-avro的类完全隔离。你在代码里需要用哪个版本的类,就导入对应的包就行。
方案3:拆分项目为子模块(物理隔离类路径)
如果你的代码逻辑本身可以拆分,把项目拆成多个子模块是最稳妥的方式:
- 子模块A:仅依赖
commons-avro,封装需要这个库的业务逻辑 - 子模块B:仅依赖
commons-avro-enum,封装需要这个库的业务逻辑 - 主模块:只依赖子模块A和B,不直接引入冲突的两个库
每个子模块的类路径是独立的,自然就不会出现类冲突问题,还能让项目结构更清晰。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

