首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >大型Java系统依赖项管理

大型Java系统依赖项管理
EN

Stack Overflow用户
提问于 2009-09-21 18:36:48
回答 8查看 4.4K关注 0票数 30

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

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

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

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

我想这一切都归结于每个包的依赖规范( POM)的质量。对于ActiveMQ,没有作用域声明,所以任何对ActiveMQ的引用都将下载它的所有依赖项,除非我们手动排除那些我们知道不需要的依赖项。

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

这是当前的情况,还是我遗漏了什么?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-09-21 18:59:56

你说的完全正确

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

我要添加的唯一一件事是将POM或任何其他形式的元数据作为起点。例如,ActiveMQ为你提供了所有的依赖项,这是非常有用的,但它是否真的适合你的项目,这取决于你的选择。

毕竟,即使考虑到log4j版本,您会有一个外部依赖项来选择版本还是选择您知道对您有效的版本?

至于如何选择定制依赖关系,下面是您可以使用Ivy做的事情:

不需要的包

Derby检索了一大堆包(例如Jetty、

和Geronimo ),我知道使用ActiveMQ并不需要这些包。

这通常是由于应用程序的模块性差造成的。例如,应用程序的某些部分需要Jetty,但是即使您不使用Jetty,最终也会得到这种传递依赖。

您可能想要研究一下ivy exclude mechanism

代码语言:javascript
复制
<dependency name="A" rev="1.0">
  <exclude module="B"/>
</dependency>

依赖项版本

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

也许我误解了这一点,但Ivy的冲突解决方案中没有手动元素。这里有一个default conflict managers的列表

  • all:此冲突管理器通过选择所有修订来解决冲突。也称为NoConflictManager,它确实驱逐了所有模块。
  • latest-time:此冲突管理器仅选择“最新”版本,最新版本被定义为时间上的最新版本。请注意,计算时间的最新版本的成本很高,所以如果可以的话,最好使用最新版本。
  • latest-revision:此冲突管理器仅选择‘最新’版本,最新版本由修订版本的字符串比较定义。
  • latest-compatible:此冲突管理器选择冲突中的最新版本,这可能会产生一组兼容的依赖项。这意味着该冲突管理器最终不允许任何冲突(就像严格的冲突管理器一样),除非它遵循尽力而为的策略来尝试找到一组兼容的模块(根据版本constraints);
  • strict:,只要发现冲突,该冲突管理器就会抛出异常(即导致构建失败)。

如果需要,您可以使用provide your own conflict manager

票数 11
EN

Stack Overflow用户

发布于 2009-09-21 18:57:12

差不多就是这样。maven依赖系统( Ivy或多或少遵循该系统)将为其依赖项添加必要的元数据的工作留给了各个项目。大多数人都不这么认为。

如果你走了那条路,你就得花时间设置排除项。

对于推荐OSGi的帖子,OP说他不愿意为Maven重新设计他的构建系统,我认为他不会想重新设计他的应用程序以符合OSGi。此外,许多与OSGi兼容的开放源码软件项目(并不像您希望的那样多)的元数据与Maven元数据一样糟糕

票数 5
EN

Stack Overflow用户

发布于 2009-09-21 19:07:10

在您列出的依赖项中,以下项在Maven中定义为optional (也请参阅activemq-core一书中的relevant section )。

  • org.apache.derby:derby
  • org.apache.geronimo.specs:geronimo-jta_1.0.1B_spec

我没有看到对Jetty的直接依赖,所以它可能会从一个可选的依赖中过渡地包含进来。

在Maven中,可选依赖关系是自动处理的。本质上,任何声明为可选的依赖项都必须在你的pom中重新声明,才能使用它。来自上面链接的文档:

可选依赖关系在不可能(无论出于什么原因)将项目拆分成子模块的情况下使用。这个想法是,一些依赖项仅用于项目中的某些功能,如果不使用该功能,则不需要。理想情况下,这样的功能应该被拆分成依赖于核心功能的子模块,因为如果您决定使用子项目的功能,那么project...this新子项目将只有非可选的依赖项。

然而,由于项目不能被拆分(同样,由于某种原因),这些依赖项被声明为可选的。如果用户想要使用与可选依赖项相关的功能,则必须在自己的项目中重新声明该可选依赖项。这不是处理这种情况的最清晰的方法,但同样,可选依赖项和依赖项排除都是权宜之计。

我不确定您是否可以将Ivy配置为忽略可选的依赖项,但您可以将其配置为exclude dependencies。例如:

代码语言:javascript
复制
<dependency name="A" rev="1.0">
  <exclude module="B"/>
</dependency>

我知道这并不完全令人满意。Ivy可能确实支持可选的依赖项(如果我发现了什么,我会进一步查看并更新),但排除机制至少允许您管理它们。

关于你问题的最后一部分。Maven将解析log4j的依赖版本,如果版本兼容,它将自动从列出的版本中选择“最近”的版本。

Introduction to the Dependency Mechanism

  • 依赖项中介-当遇到多个版本的工件时,它确定将使用哪个版本的依赖项。目前,Maven2.0只支持使用“最近的定义”,这意味着它将使用依赖关系树中与您的项目最接近的依赖关系的版本。您总是可以通过在项目的POM中显式声明它来保证版本。请注意,如果两个依赖项版本在依赖关系树中的深度相同,则直到Maven2.0.8之前都没有定义哪个版本会胜出,但从Maven2.0.9开始,重要的是声明中的顺序:第一个声明取胜。

代码语言:javascript
复制
- "nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0

在版本不兼容的情况下,你有一个比依赖解析更大的问题。我相信Ivy也有类似的模式,但我不是专家。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1456084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档