Maven依赖解析(冲突)

问题描述 投票:0回答:5

假设我有四个项目:

  • 项目 A(依赖于 B 和 D)
  • 项目 B(依赖于 D)
  • 项目 C(依赖于 D)
  • D 项目

在这种情况下,如果我运行项目 A,Maven 将正确解析对 D 的依赖关系。如果我理解正确,Maven 总是采用最短路径的依赖关系。由于 D 是 A 的直接依赖项,因此将使用 B 中指定的 D。

但现在假设这个结构:

  • 项目 A(依赖于 B 和 C)
  • 项目 B(依赖于 D)
  • 项目 C(依赖于 D)
  • D 项目

在这种情况下,解析 D 的路径具有相同的深度。发生的情况是 Maven 会发生冲突。我知道可以告诉 Maven 他应该排除依赖项。但我的问题是如何解决此类问题。我的意思是,在现实世界的应用程序中,您有很多依赖项,也可能有很多冲突。

最佳实践解决方案真的是排除某些东西还是有其他可能的解决方案?当我突然收到 ClassNotFound Exception 时,我发现很难处理,因为某些版本已更改,这导致 Maven 采用不同的依赖项。当然,了解这个事实可以更容易地猜测问题是依赖冲突。

我正在使用 maven 2.1-SNAPSHOT。

java maven-2 maven
5个回答
115
投票
解决此类情况的 Maven 方法是在项目的根 pom 中包含一个

<dependencyManagement>

 部分,您可以在其中指定将使用哪个库的版本。 

编辑:

<dependencyManagement> <dependencies> <dependency> <groupId>foo</groupId> <artifactId>bar</artifactId> <version>1.2.3</version> </dependency> </dependencies> </dependencyManagement>

现在,无论依赖项请求哪个版本的库 foo:bar,该项目和所有子项目都将始终使用版本 1.2.3。

参考:

  • 依赖管理

40
投票
Maven 可以处理这两种情况,不会发生任何冲突。当需要两个版本的传递依赖时,就会存在冲突。您描述的

ClassNotFoundException

是应用程序(或依赖项)尝试使用实际使用的冲突依赖项版本中不可用的类的结果。
有多种方法可以解决该问题。

    更新您正在使用的依赖于冲突依赖项的库的版本,以便它们都依赖于该依赖项的同一版本
  1. 将冲突的依赖项声明为项目与要包含的版本的直接依赖项(在示例中,是包含缺少类的版本)
  2. 通过 POM 的
  3. <dependencyManagement>
     部分指定传递依赖项应使用哪个版本的冲突依赖项
  4. 使用
  5. <exclusion>
     显式排除冲突依赖项的不需要版本,使其不包含在依赖它们的依赖项中
    

29
投票
这根本不是maven的问题,而是java的问题。 如果项目 B 和项目 C 需要项目 D 的两个不兼容版本,那么您不能在项目 A 中同时使用它们。

不幸的是,正如您所知,解决此类冲突的 Maven 方法是选择排除哪些冲突。

使用

mvn dependency:analyze

mvn dependency:tree
 有助于查找您存在的冲突。


24
投票
您可以使用规则

依赖收敛在整个项目中强制一致的依赖关系。

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.3.1</version> <executions> <execution> <id>enforce</id> <configuration> <rules> <DependencyConvergence/> </rules> </configuration> <goals> <goal>enforce</goal> </goals> </execution> </executions> </plugin>
    

9
投票
一种可能的策略是为主项目指定要使用的 D 版本(例如最新版本)。但是,如果库 D 不向后兼容,则会遇到 kukudas 所述的问题 - 不可能在项目中使用这两个库。

在这种情况下,可能需要在旧版本中使用 B 或 C,以便两者都依赖于 D 的兼容版本。

© www.soinside.com 2019 - 2024. All rights reserved.