大型 Java 系统依赖关系管理不需要的软件包依赖项版本

2022-09-01 12:13:16

我们有一个大型(>500,000 LOC)Java系统,依赖于40-50个OSS包。系统是用Ant构建的,目前依赖关系管理是手动处理的。我正在调查Ivy和/或Maven以自动化依赖关系。我们去年将Maven视为一个构建自动化系统,并拒绝了它,因为它需要完全重组我们的系统以匹配Maven的架构。现在,我希望仅自动执行依赖项管理任务。

我对常春藤做了一些实验,但遇到了问题。例如,当我指定ActiveMQ作为依赖项,并告诉Ivy使用Maven存储库中的POM进行依赖项规范时,Ivy检索了一堆包(例如Jetty,Derby和Geronimo),我知道这些包不需要只使用ActiveMQ。

如果我在ivysettings中设置usepoms=“false.xml它只获取activemq.jar,但这似乎违背了Ivy的目的,并将其降级为一个简单的jar-fetcher,具有手动构建的依赖规范。

这里有一个更大的问题,在Windows中曾经被称为“DLL地狱”。在某些情况下,两个直接的第一级依赖项将指向同一传递依赖项的不同版本(例如 log4j.jar)。类路径中只能有一个 log4j.jar,因此依赖关系解析涉及手动确定哪个版本与我们系统中的所有客户端兼容。

我想这一切都归结为每个包的依赖规范(POM)的质量。在 ActiveMQ 的情况下,没有范围声明,因此对 ActiveMQ 的任何引用都将下载其所有依赖项,除非我们手动排除我们知道不需要的依赖项。

在log4j的情况下,自动依赖关系解析将要求所有log4j的客户端(依赖于log4j的其他软件包)针对所有先前版本的log4j进行验证,并在POM中提供兼容的log4j版本的范围(或列表)。这可能要求太多了。

这是目前的情况,还是我错过了什么?


答案 1

你说得对

我想这一切都归结为每个包的依赖规范(POM)的质量。

我唯一要补充的是将POM或任何其他形式的元数据作为起点。例如,ActiveMQ为您提供了所有依赖项,这是非常有用的,但是由您来选择它是否确实适合您的项目。

毕竟,即使考虑到log4j版本,您是否会让外部依赖项选择版本或选择您知道适合您的版本?


至于如何选择定制依赖关系,以下是您可以对 Ivy 执行的操作:

不需要的软件包

Ivy检索了一堆软件包(例如Jetty,Derby和Geronimo),我知道这些软件包不需要使用ActiveMQ。

这通常是由于应用程序中的模块化程度较差而发生的。例如,应用程序的某些部分需要 Jetty,但即使您不使用它,您最终也会得到这种可传递依赖项。

您可能想研究常春藤排除机制

<dependency name="A" rev="1.0">
  <exclude module="B"/>
</dependency>

依赖项版本

类路径中只能有一个 log4j.jar,因此依赖关系解析涉及手动确定哪个版本与我们系统中的所有客户端兼容。

也许我误读了这一点,但艾薇的冲突解决方案中没有手动元素。有一个缺省冲突管理器列表:

  • all:此冲突管理器通过选择所有修订来解决冲突。也称为NoConflictManager,它会逐出任何模块。
  • 最新时间:此冲突管理器仅选择“最新”修订版,最新定义为最晚时间。请注意,最新时间的计算成本很高,因此如果可以的话,最好选择最新版本。
  • latest-revision:此冲突管理器仅选择“最新”修订版,最新的修订版由修订版的字符串比较定义。
  • 最新兼容:此冲突管理器在冲突中选择最新版本,这可能导致一组兼容的依赖项。这意味着最终这个冲突管理器不允许任何冲突(如严格的冲突管理器),除了它遵循一个尽力的策略来尝试找到一组兼容的模块(根据版本约束);
  • strict:每当发现冲突时,此冲突管理器都会引发异常(即导致构建失败)。

如果需要,您可以提供自己的冲突管理器


答案 2

差不多就是这样。maven依赖系统(Ivy或多或少遵循)将其留给各个项目,以很好地为其依赖关系添加必要的元数据。大多数人没有。

如果您选择这条路,则需要花时间设置排除项。

对于推荐OSGi的海报,OP说他不愿意为Maven重新构建他的构建系统,我不认为他会想要重新构建他的应用程序以符合OSGi。此外,许多符合OSGi标准的OSS项目(而且没有你希望的那么多)的元数据与Maven一样糟糕或更差。


推荐