java Maven依赖顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12624892/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:36:12  来源:igfitidea点击:

Maven dependency order

javamavenjar

提问by Hilikus

In my project there is a class implementing an interface. The interface comes from a dependency. I have another dependency that itself has a dependency on a jar that also contains the same interface, except a version with more methods; the two jars containing the same package-interface DON'T have the same groupId or artifactId.
Compilation is failing because the compiler complains that the class in my project is not implementing all the methods. I realized it is because the compiler is taking the interface reference from the wrong jar. My question is, why is maven using the interface from the transitive dependency instead of the one from the jar that I explicitly mention in the project POM?I can see the jar that is used appears earlier in the definition (so i imagine in the classpath as well), but i thought in these cases maven resolved it by using the colliding class/interface from the dependency with the shortest path

在我的项目中有一个实现接口的类。接口来自依赖项。我有另一个依赖项,它本身依赖于也包含相同接口的 jar,除了具有更多方法的版本;包含相同包接口的两个 jar 不具有相同的 groupId 或 artifactId。
编译失败,因为编译器抱怨我的项目中的类没有实现所有方法。我意识到这是因为编译器从错误的 jar 中获取接口引用。我的问题是,为什么 maven 使用来自传递依赖项的接口,而不是我在项目 POM 中明确提到的 jar 中的接口?我可以看到使用的 jar 出现在定义的较早位置(所以我也想象在类路径中),但我认为在这些情况下,maven 通过使用最短路径依赖项中的冲突类/接口来解决它

Here is part of the dependency tree. Note that this is greppedbut it can still be seen that javax.servlet:servlet-api(the one actually used) is deeper in the tree compared to tomcat:servlet(the one that should be used)

这是依赖树的一部分。请注意,这是grepped,但仍然可以看到javax.servlet:servlet-api(实际使用的)与tomcat:servlet(应该使用的)相比在树中更深

[builder@ca-rd-build11 proj]$ mvn dependency:tree | grep servlet
[INFO] |  +- javax.servlet:servlet-api:jar:2.4:compile
[INFO] +- tomcat:servlet:jar:4.0.6:compile

I'm using maven 3.0.4

我正在使用 Maven 3.0.4

回答by Sean Patrick Floyd

why is maven using the interface from the transitive dependency instead of the one from the jar that I explicitly mention in the project POM?

为什么 maven 使用传递依赖中的接口而不是我在项目 POM 中明确提到的 jar 中的接口?

Because, to Maven, the two have nothing to do with each other. Maven doesn't know about class or package names, Maven just knows about groupId and artifactId. Since those are not the same, maven doesn't have any reason to omit the transitive dependency.

因为,对Maven来说,两者没有任何关系。Maven 不知道类或包名,Maven 只知道 groupId 和 artifactId。由于这些不一样,maven 没有任何理由省略传递依赖。

And if I am correct, Maven places the dependencies on the classpath in the order they are defined, i.e. the transitive dependencies of dependency aappear before dependency b.

如果我是对的,Maven 会按照定义的顺序将依赖项放在类路径上,即依赖项的传递依赖项a出现在依赖项之前b

回答by Nick Wilson

When you declare your dependency on the other jar file you can tell it to exclude the transitive dependency on the conflicting jar file:

当您声明对另一个 jar 文件的依赖时,您可以告诉它排除对冲突 jar 文件的传递依赖:

    <dependency>
        <groupId>group</groupId>
        <artifactId>artifact</artifactId>
        <version>1.0.0</version>
        <exclusions>
            <exclusion>
                <groupId>othergroup</groupId>
                <artifactId>ArtifactToExclude</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

回答by Voicu

For future visitors(since the title is generic):

对于未来的访问者(因为标题是通用的):

In Maven you have two categories of dependencies:

在 Maven 中,您有两类依赖项:

  • (external) dependencies: what you define directly in your pom.xmlfiles inside <dependencies>
  • transitive dependencies: the dependencies your pom.xmldependencies require (automatically included, together with their dependencies, and so on)
  • (外部)依赖项:你直接在你的pom.xml文件里面定义的<dependencies>
  • 传递依赖:你的pom.xml依赖需要的依赖(自动包含,连同它们的依赖等等)

As per the official Maven documentationthe following mediation is applied when multiple versions are encountered as dependencies:

根据官方 Maven文档,当遇到多个版本作为依赖项时,将应用以下中介:

Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, the first declaration wins.

Example: if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0.

Maven 选择“最近的定义”。也就是说,它使用依赖项树中与您的项目最接近的依赖项的版本。您始终可以通过在项目的 POM 中明确声明来保证版本。请注意,如果两个依赖版本在依赖树中的深度相同,则第一个声明获胜。

示例:如果 A、B 和 C 的依赖项定义为 A -> B -> C -> D 2.0 和 A -> E -> D 1.0,则在构建 A 时将使用 D 1.0,因为从 A 到D 到 E 较短。您可以在 A 中显式添加对 D 2.0 的依赖项以强制使用 D 2.0。

In the above example, A is the actual project, B and E are external dependencies defined in its pom.xmlfile, and C and D are transitive dependencies.

在上面的例子中,A是实际的项目,B和E是在其pom.xml文件中定义的外部依赖,C和D是传递依赖。