我们有一个依赖于特定库的Java程序。 我们已经创建了第二个库,该库具有与第一个库非常相似的API,但是,这个库是内部制作的,我们已准备好开始测试它。
为了进行测试,我们想用新库的 jar 替换 Java 程序中的 jar。 问题是新库没有完全相同的命名空间,因此导入语句不会对齐。例如
爪哇程序
import someLibrary.x.y.Foo;
public class Main {
public static void main(String[] args){
new Foo().bar();
}
}
新库具有相同的 API 但不同的命名空间
anotherLibrary.x.y.Foo;
问:如何使用类加载器或其他工具来运行 Java 程序,但替换依赖项并将导入语句重定向到另一个命名空间?
[编辑] - 我们无法访问Java程序的源代码。我们可以更改此程序以使用我们的新库,但在经过全面测试之前,我们不想这样做。
我能想到的唯一解决方案是编写一个自定义ClassLoader
,该将更改字节码以更改方法引用和字段引用以更改类名。
简单的解决方案怎么样:
- 创建主程序的一个分支(在 git 或您使用的任何源代码管理工具中(:
- 应用使用新库所需的所有更改(更改所有导入(
- 在测试环境中部署并广泛测试
- 当您感到足够自信时,合并回母版
另一种解决方案可能是:
- 从新库创建分支
- 更改导入,使其看起来与旧导入完全相同(包含所有包(
- 在应用程序中用新库替换旧库
- 在测试环境中部署并广泛测试
- 当您准备好将新库部署到生产环境并继续在生产环境中工作一个月或更长时间时(直到您真正有信心为止(
- 在一个月内更改所有导入(基本上从具有"旧"导入的分支移动到具有库和应用程序中实际导入的分支。
更新
如果您使用 maven,也可以自动重新定位库版本的包。
Maven shade插件有一个目标relocate
可以用来"重新定位"库的包,就像现有库的包一样。查看阴影插件的文档