Maven依赖解析(冲突)

kuk*_*das 67 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.

Sea*_*oyd 79

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

编辑:

<dependencyManagement>
  <dependencies>
    <dependency>
        <groupId>foo</groupId>
        <artifactId>bar</artifactId>
        <version>1.2.3</version>
    </dependency>
   </dependencies>
</dependencyManagement>
Run Code Online (Sandbox Code Playgroud)

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

参考:

  • @Nitul 那么你基本上被搞砸了。您唯一的选择是使用诸如 maven shade 插件之类的东西重新打包依赖项之一 (3认同)
  • 为了澄清,`dependencyManagement`中指定的版本号适用于传递依赖项,而项目依赖项没有显式版本.但是具有显式版本的项目依赖项会覆盖`dependencyManagement`部分中的版本. (3认同)

Dan*_*iel 28

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

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


Buh*_*uhb 17

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

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

使用mvn dependency:analyzemvn dependency:tree帮助您找到您所遇到的冲突.


Mar*_*szS 14

您可以使用规则依赖性收敛在整个项目中强制实施一致的依赖关系.

 <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>
Run Code Online (Sandbox Code Playgroud)


小智 6

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

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