Maven依赖解析(冲突)

时间:2011-08-24 12:27:57

标签: java maven-2 maven

假设我有四个项目:

  • 项目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。

5 个答案:

答案 0 :(得分:72)

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

编辑:

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

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

<强>参考:

答案 1 :(得分:24)

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

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

答案 2 :(得分:16)

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

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

使用mvn dependency:analyzemvn dependency:tree有助于查找您遇到的冲突。

答案 3 :(得分:10)

您可以使用规则enforce在整个项目中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>

答案 4 :(得分:5)

一种可能的策略是为主项目指定要使用的D版本(最新版本f.g.)。但是,如果库D不向后兼容,则存在kukudas所述的问题 - 在项目中不可能同时使用这两个库。

在这种情况下,可能需要在旧版本中使用B或C,这样两者都将取决于D的兼容版本。