Java可传递依赖性问题,无有效解决方案

Java可传递依赖性问题,无有效解决方案,java,maven,Java,Maven,我正在使用Maven来管理我的项目依赖关系。我的依赖关系树在包B上有冲突,如: A -> B (v1.4) C -> B (v1.5) 事实证明,包A依赖于v1.5中修复的bug,包C需要1.5中没有的功能 具有大量依赖项的大型java项目如何管理这些类型的问题?即使包A看起来在v1.5的表面级别上工作,我仍然觉得假设在所有边缘情况下它都能像以前一样工作是有风险的 请注意,这是一种假设情况,因此不必知道这些包代表哪些包 最后,只有一个依赖项在运行时生效,您可以使用和来控制可传递的依

我正在使用Maven来管理我的项目依赖关系。我的依赖关系树在包B上有冲突,如:

A -> B (v1.4)
C -> B (v1.5)
事实证明,包
A
依赖于v1.5中修复的bug,包
C
需要1.5中没有的功能

具有大量依赖项的大型java项目如何管理这些类型的问题?即使包A看起来在v1.5的表面级别上工作,我仍然觉得假设在所有边缘情况下它都能像以前一样工作是有风险的


请注意,这是一种假设情况,因此不必知道这些包代表哪些包

最后,只有一个依赖项在运行时生效,您可以使用
来控制可传递的依赖项



每当依赖项发生冲突时,Maven都会根据最近的wins策略选择一个版本,这意味着将选择依赖项树中离模块较近的任何版本,而忽略所有其他版本。如果
v1.4
在依赖关系树中更接近,则即使它比
v1.5
旧,也会被选中

要控制要使用的依赖项,可以在模块中定义
依赖项管理
,以设置Maven应使用的版本:

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>com.example</groupId>
         <artifactId>packageB</artifactId>
         <version>1.5</version>
      </dependency>
      <!-- other dependencies -->
   </dependencies>
</dependencyManagement>

com.example
包装B
1.5
或者,您可以在具有可传递依赖项的依赖项中排除要忽略的版本:

<dependency>
   <groupId>com.example</groupId>
   <artifactId>packageA</artifactId>
   <exclusions>
      <exclusion>
         <groupId>com.example</groupId>
         <artifactId>packageB</artifactId>
      </exclusion>
   </exclusions>
</dependency>

com.example
包装
com.example
包装B

只有Maven和classic JAR,没有结果:这就是为什么我们称之为“依赖地狱”(“dll地狱”是最初的,注意押韵:)

然而,有一种技术专门用于解决这个问题:OSGi。通过大量复杂复杂的类加载器处理,OSGi设法满足每个包的特定依赖性需求。捆绑包A可以使用捆绑包B v1.4,同时捆绑包C可以使用B v1.5


OSGi已经存在十多年了,它似乎既没有兴旺也没有消亡;相反,它正在以缓慢的速度获得采用,因此越来越多的JAR升级到OSGi捆绑包。

这不是maven的问题,而是java的问题。Maven只是简单地将其公开,并使识别和管理问题成为可能。有很多解决方案:大多数(如果不是全部的话)都是作为独立的类加载器实现的,通常在JavaEE或OSGi容器中


另外:一般来说,项目中不允许使用可传递依赖项——如果使用类,请将一级依赖项添加到它所属的库中。至少通过这种方式,可以很容易地看到您的依赖项在哪里,以及您的问题可能在哪里。

当然,但在这种情况下,我在这两种情况下都有问题(或者至少我不能确定它不会)。在这种情况下,你如何选择一个而不是另一个呢?选择最新的,确保你的代码与最新的API更改兼容,但在这种情况下,我不控制A和C,所以我无法控制如何验证正确性。我知道我可以提交补丁,运行我自己的测试套件,等等,但这在具有许多可传递依赖项的大型项目中成为一个棘手的问题。您最终可以为A和CBA创建自己的构建。但是,您如何确定所有其他依赖项都与更新的库一起工作?在一个大型java项目中,我不明白这怎么会不会对整个世界造成严重破坏。在大型项目中,是更常见的OSGi技术,还是仅仅依赖于第三方LIB的大多数次要更新不会(无意中)有破坏性的更改?我们主要通过(例如)将A升级到使用B v1.5的版本来解决这些问题。而且,库几乎从不依赖于其他库中的bug;相反,A的开发人员会将错误通知B的开发人员,甚至自己提交补丁。然后,B将收到一个次要版本(比如1.4.12),订单将恢复。这是开源开发的一大优势。