为啥 Maven 依赖项的顺序很重要?

Posted

技术标签:

【中文标题】为啥 Maven 依赖项的顺序很重要?【英文标题】:Why order of Maven dependencies matter?为什么 Maven 依赖项的顺序很重要? 【发布时间】:2015-10-22 19:33:31 【问题描述】:

我之前认为 Maven 依赖项的顺序无关紧要,并认为这是它的优点。这是我以前的 pom.xml 的依赖项:

<dependencies>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.19</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>2.19</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.19</version>
    </dependency>

</dependencies>

效果很好,今天我想将 spring 依赖移到底部,以便那些与球衣相关的可以在一起。但是我不能再让它工作,我的码头抱怨:

[ERROR] Failed to execute goal org.eclipse.jetty:jetty-maven-plugin:9.3.0.M1:run (default-cli) on project mtest: Execution default-cli of goal org.eclipse.jetty:jetty-maven-plugin:9.3.0.M1:run failed: A required class was missing while executing org.eclipse.jetty:jetty-maven-plugin:9.3.0.M1:run: org/apache/commons/logging/LogFactory

这真的很令人困惑,所以我必须关注依赖顺序吗?我怎么知道正确的顺序?

【问题讨论】:

可能不会直接回答你的问题,但我通常只是declare the commons-logging。检查包含后是否仍有问题 @peeskillet,包含它后,我的 Jetty 启动成功,但我的服务无法运行。 【参考方案1】:

依赖关系的顺序确实很重要,因为 Maven 如何解决传递依赖关系,从版本 2.0.9 开始。摘自documentation:

(...) 这决定了当遇到工件的多个版本时将使用哪个版本的依赖项。 (...) 您始终可以通过在项目的 POM 中明确声明来保证版本。 (...) 从 Maven 2.0.9 开始,重要的是声明中的顺序:第一个声明获胜

【讨论】:

我不确定为什么这个答案被否决了。它至少部分回答了声明顺序为何重要的问题。 请注意,Maven 首先选择与您的项目“最近”的工件版本。只有当两个不同的版本同样接近时,它才会使用顺序来解决冲突。【参考方案2】:

为了扩展另一个答案(声明顺序会影响 Maven 对传递依赖的依赖中介),您可以使用一些工具:

mvn dependency:tree [-Dscope=[runtime|test]] 将向您显示所选范围内可用的依赖项。 See here for details mvn dependency:build-classpath 为您提供类路径上可用依赖项的顺序(如果两个或更多类路径条目具有相同的类,则较早的条目获胜)。 See here for details

我不太了解您的情况,但通常情况下,您在编译/运行时会使用 1 个或多个 jar 的错误版本。 Declaring your own version of the library in question or locking down the version 和 &lt;dependencyManagement&gt; 是这里的选项。

现在回答您的另一个问题 - 在声明依赖项时,您如何知道正确的顺序是什么?

我的建议 - 正确的声明顺序是按照您希望它们的顺序为您提供所需依赖项的版本。使用上述工具检查您的依赖关系,并在必要时调整声明的顺序。

请注意,大多数 jar 包含名称不连贯的类,因此 jar 出现在类路径中的确切顺序通常并不那么重要。我注意到的唯一例外是some jars in SLF4J,它故意隐藏了它打算替换的其他记录器库中的类。

【讨论】:

以上是关于为啥 Maven 依赖项的顺序很重要?的主要内容,如果未能解决你的问题,请参考以下文章

为啥有时会跳过 maven 依赖项中的版本号?

为啥不能使用pom文件中的maven依赖?

在 OSGi 包中添加第三方 Maven 依赖项的最佳方法

gradle 到 maven 的转换,在依赖项的依赖项的版本名称中解析通配符“+”?

具有 maven 依赖项的 Java ClassNotFoundException

是否有一个 Maven 插件可以验证传递依赖项的冲突版本?