我们有一个大型的(>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版本的范围(或列表)。这可能要求太高了。
这是当前的情况,还是我遗漏了什么?
发布于 2009-09-21 18:59:56
你说的完全正确
我想这一切都归结为每个包的依赖规范( POM)的质量。
我要添加的唯一一件事是将POM或任何其他形式的元数据作为起点。例如,ActiveMQ为你提供了所有的依赖项,这是非常有用的,但它是否真的适合你的项目,这取决于你的选择。
毕竟,即使考虑到log4j版本,您会有一个外部依赖项来选择版本还是选择您知道对您有效的版本?
至于如何选择定制依赖关系,下面是您可以使用Ivy做的事情:
不需要的包
Derby检索了一大堆包(例如Jetty、
和Geronimo ),我知道使用ActiveMQ并不需要这些包。
这通常是由于应用程序的模块性差造成的。例如,应用程序的某些部分需要Jetty,但是即使您不使用Jetty,最终也会得到这种传递依赖。
您可能想要研究一下ivy exclude mechanism
<dependency name="A" rev="1.0">
<exclude module="B"/>
</dependency>依赖项版本
类路径中只能有一个log4j.jar,因此依赖项解析涉及手动确定哪个版本与系统中的所有客户端兼容。
也许我误解了这一点,但Ivy的冲突解决方案中没有手动元素。这里有一个default conflict managers的列表
如果需要,您可以使用provide your own conflict manager。
发布于 2009-09-21 18:57:12
差不多就是这样。maven依赖系统( Ivy或多或少遵循该系统)将为其依赖项添加必要的元数据的工作留给了各个项目。大多数人都不这么认为。
如果你走了那条路,你就得花时间设置排除项。
对于推荐OSGi的帖子,OP说他不愿意为Maven重新设计他的构建系统,我认为他不会想重新设计他的应用程序以符合OSGi。此外,许多与OSGi兼容的开放源码软件项目(并不像您希望的那样多)的元数据与Maven元数据一样糟糕
发布于 2009-09-21 19:07:10
在您列出的依赖项中,以下项在Maven中定义为optional (也请参阅activemq-core一书中的relevant section )。
我没有看到对Jetty的直接依赖,所以它可能会从一个可选的依赖中过渡地包含进来。
在Maven中,可选依赖关系是自动处理的。本质上,任何声明为可选的依赖项都必须在你的pom中重新声明,才能使用它。来自上面链接的文档:
可选依赖关系在不可能(无论出于什么原因)将项目拆分成子模块的情况下使用。这个想法是,一些依赖项仅用于项目中的某些功能,如果不使用该功能,则不需要。理想情况下,这样的功能应该被拆分成依赖于核心功能的子模块,因为如果您决定使用子项目的功能,那么project...this新子项目将只有非可选的依赖项。
然而,由于项目不能被拆分(同样,由于某种原因),这些依赖项被声明为可选的。如果用户想要使用与可选依赖项相关的功能,则必须在自己的项目中重新声明该可选依赖项。这不是处理这种情况的最清晰的方法,但同样,可选依赖项和依赖项排除都是权宜之计。
我不确定您是否可以将Ivy配置为忽略可选的依赖项,但您可以将其配置为exclude dependencies。例如:
<dependency name="A" rev="1.0">
<exclude module="B"/>
</dependency>我知道这并不完全令人满意。Ivy可能确实支持可选的依赖项(如果我发现了什么,我会进一步查看并更新),但排除机制至少允许您管理它们。
关于你问题的最后一部分。Maven将解析log4j的依赖版本,如果版本兼容,它将自动从列出的版本中选择“最近”的版本。
从Introduction to the Dependency Mechanism
- "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也有类似的模式,但我不是专家。
https://stackoverflow.com/questions/1456084
复制相似问题