Maven依赖关系解析(冲突)


78

假设我有四个项目:

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

在这种情况下,如果我运行项目A,则Maven将正确地将依赖关系解析为D。由于D是A的直接依赖项,因此将使用B内指定的D而不是D。

但是现在假设这种结构:

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

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

最佳实践解决方案是否真的排除了某些东西,或者还有其他可能的解决方案吗?我突然遇到ClassNotFound异常时很难处理,因为某些版本已更改,这导致Maven采用了不同的依赖关系。当然,了解这一事实使我们更容易猜测问题是依赖冲突。

我正在使用Maven 2.1-SNAPSHOT。


2
我认为您不应该使用2.1-SNAPSHOT版本,它是DEV版本。Maven 2在2.2.1最终版本中可用。

4
顺便说一句,Maven 3.x已经稳定了一段时间,并且比maven 2.x更快,更可靠
Sean Patrick Floyd

3
钻石是程序员的最大敌人……
托尼·兰帕达(TonyLâmpada)2012年

@Sean Patrick Floyd所有行家版本都比SNAPSHOT稳定:)
MariuszS 2013年

Answers:


88

解决这种情况的一种行之有效的方法是<dependencyManagement>在项目的根pom中包含一个部分,您可以在其中指定将使用哪个版本的库。

编辑:

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

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

参考:


如果版本与项目D,项目B的版本不同(该项目依赖于D1.0)-不能与D2.0一起使用项目C(具有一个D2.0依赖于它)-不能与D1.0一起使用
Nitul

2
@Nitul,那么您基本上就搞砸了。你唯一的选项,然后是重新包装使用类似Maven的树荫插件依赖项之一
肖恩·帕特里克·弗洛伊德

4
为了明确起见,中指定的版本号dependencyManagement适用于传递性依赖项,而项目依赖项没有显式版本。但是具有显式版本的项目依赖项会覆盖本dependencyManagement节中的版本。
pnewhook

31

Maven可以处理两种情况而不会发生任何冲突。当需要两个版本的传递依赖项时,将存在冲突。在ClassNotFoundException你的描述从应用程序(或依赖)的结果尝试使用的实际被使用的冲突依赖的版本中不可用的类。有多种方法可以解决此问题。

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

21

从根本上讲,这不是Maven问题,而是Java问题。如果项目B和项目C需要项目D的两个不兼容版本,则不能在项目A中同时使用它们。

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

使用mvn dependency:analyzemvn dependency:tree帮助您查找有什么冲突。


+1。我要说的是,不向后兼容的工件应更改其groupId和/或artifactId。
肖恩·帕特里克·弗洛伊德

是的,但这只花了一半。工件不得包含具有相同包和名称的类。
2011年

是的,很不幸的。在这种情况下,您将需要ProGuard或Maven阴影插件
Sean Patrick Floyd

OSGI是否可以解决这种假设情况?(并不是建议这是一个简单的解决方案-只是问问。)
jhericks

可能吧。我不知道OSGI有什么好说的。
2011年

18

您可以使用规则Dependency Convergence在整个项目中实施一致的依赖关系

 <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版本(最新的fg)。但是,如果库D不向后兼容,则您将遇到kukudas所述的问题-在项目中无法同时使用两个库。

在这种情况下,可能有必要在较旧的版本中使用B或C,以便两者都取决于D的兼容版本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.