Java 8。
假设有一个旧版本的widget
libray,其Maven坐标为widgetmakers:widget:1.0.4
,其中定义了一个类,如下所示:
public class Widget {
private String meow;
// constructor, getters, setters, etc.
}
几年过去了。此widget
库的维护者决定Widget
永远不应该meow
,而应该确实bark
。widgetmakers:widget:2.0.0
因此,制作了一个新版本,Maven坐标为Widget
,public class Widget {
private Bark bark;
// constructor, getters, setters, etc.
}
如下:
myapp
所以现在我去构建我的应用build.gradle
。并且,想要使用我所有依赖项的最新稳定版本,我声明我的依赖项(在dependencies {
compile (
,'org.slf4j:slf4j-api:1.7.20'
,'org.slf4j:slf4j-simple:1.7.20'
,'bupo:fizzbuzz:3.7.14'
,'commons-cli:commons-cli:1.2'
,'widgetmakers:widget:2.0.0'
)
}
内):
fizzbuzz
现在让我们假设这个(虚构的)widget
库的总是依赖于Widget
库的1.x版本,其中meow
会{ {1}}。
现在,我在编译类路径中指定了widget
的两个版本:
widgetmakers:widget:1.0.4
由fizzbuzz
库引入,作为其依赖项;和widgetmakers:widget:2.0.0
很明显,根据首先加载Widget
版本的Widget#meow
,我们会有Widget#bark
或fizzbuzz
。
Gradle是否提供任何帮助我的设施?是否有任何方法可以引入同一个类的多个版本,并配置Widget
类以使用旧版本的myapp/bin
,并使用我的类来使用新版本?如果没有,我能想到的唯一解决方案是:
fizzbuzz
下的包引入,然后为它们提供不同的版本前缀。诚然,我在这里看不到明确的解决方案,但我确信一些事情是可行的(但完全是hacky / nasty)。或... widget
维护者提交拉取请求以将其升级到最新的myapp
版本,或者遗憾的是,降级widget
以使用旧client.windowPosition('current', (res) => {
console.log(res.value.x, res.value.y);
});
{1}}版本。答案 0 :(得分:5)
不知道Gradle的具体细节,因为我是Maven的人,但无论如何这更为通用。你基本上有两个选择(两者都是hacky):
答案 1 :(得分:2)
Gradle只会使用您的依赖项设置类路径,它不会提供自己的运行时来封装依赖项及其传递依赖项。在运行时活动的版本将是根据类加载规则的版本,我相信这是包含该类的类路径顺序中的第一个jar。 OSGI提供的运行时可以处理这样的情况,即将推出的模块系统也是如此。
编辑:Bjorn是正确的,它会尝试解决不同版本的冲突;它会根据策略编译类路径,因此将依赖项放在文件中的顺序并不重要。但是,每个类名仍然只能获得一个课程,它不会解决OP的问题
答案 2 :(得分:0)
如果你有一个坐标相同的库的不同版本,Gradles冲突解决机制就会发挥作用。
默认解决方案策略是使用最新请求的库版本。您不会在您的dependendcy图中获得同一个库的多个版本。
如果你真的需要在运行时使用同一个库的不同版本,你必须做一些绝对可能的ClassLoader魔法,或者为其中一个库或两者做一些着色。
关于冲突解决方案,Gradle内置了默认的最新策略和失败策略,如果不同版本在依赖关系图中,则必须明确解决构建文件中的版本冲突。
答案 3 :(得分:0)
更糟糕的情况是同一个班级出现在多个罐子里。这更加阴险 - 看看来自Codahale和Dropwizard的指标罐子,两个罐子中同一类的不兼容版本。 gradle classpath-hell插件可以检测到这种恐怖。