maven 构建依赖树
上面提到的某些名称似乎建立得不够充分,而其他一些则可能需要讨论其使用方式。 考虑到这一点,我决定在自己的博客文章中探讨每种解决方案,并设定了提供足够信息的目标,以便人们可以选择最有效的方法。
第一篇文章探讨了Maven快照和发行版的依赖关系。 第二篇文章介绍了TeamCity提供的工件和快照的依赖关系,第三篇也是最后一部分将介绍TeamCity Artifactory插件提供的工件和构建的依赖关系。
内部和外部依赖
通过签出整个代码库并从头开始构建应用程序,构建过程可以完全隔离地运行。 对于项目,将相关的二进制依赖项(如果有)与项目源一起保留在VCS中。 但是,在许多其他情况下,构建脚本依赖于某种内部或外部依赖性 。
内部依赖关系由我们自己的代码满足,在代码中我们可以完全控制该项目,该项目可以拆分为多个模块或子项目。 外部依赖关系由其他人的代码(我们无法控制)来满足,我们可以使用它或将其用作客户端。 这可以是第三方库(例如Spring)或另一个团队开发的组件。
这种区别非常重要,因为内部和外部依赖项通常伴随着不同的发布和升级周期:内部依赖项可能每小时进行修改,重建和更新,而外部依赖项的发布周期显着变慢,因为用户应用更新的频率更低,如果有的话。 这主要是由于内部依赖项受我们自己控制,并且受到特定项目或模块的限制而产生了范围狭窄的影响,而外部依赖项只能按原样使用,其影响可能是公司或全球范围,它们不受任何项目限制,可以在任何地方使用。 自然,这需要更高的发行版稳定性,兼容性和成熟度标准,因此发行和更新周期较慢。
“内部与外部”相关性特征的另一方面表现为在构建脚本中如何指定其版本。 内部依赖关系通常使用快照版本定义,而外部依赖关系则使用发行版本。 Maven创造了“快照”和“发行”版本的定义,Maven开创了通过构建工具管理依赖项的想法。 如果您熟悉自动依赖项管理,请随时跳过以下部分,该部分提供了有关其工作原理的快速概述。
自动依赖管理
在Maven中,依赖关系是在构建脚本中声明性地指定的,此方法随后是一种较新的构建工具,例如Gradle , Buildr和sbt 。
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.8.6</version>
<scope>compile</scope>
</dependency>
compile "org.codehaus.groovy:groovy-all:1.8.6"
compile.with "org.apache.axis2:axis2:jar:1.6.1"
libraryDependencies += "org.twitter4j" % "twitter4j-core" % "2.2.5"
每个依赖项都通过其坐标和范围来标识。 坐标明确指定所使用的库和版本,而范围则定义其在构建任务(如编译或测试调用)中的可见性和可用性。
例如, "compile org.codehaus.groovy:groovy-all:1.8.6"
将为版本"1.8.6"
指定一个Groovy "org.codehaus.groovy:groovy-all"
发行版,用于源代码编译和测试调用。 将范围切换到“测试”或“运行时”将把库的可见性分别缩小到仅测试或仅运行时。
当开始构建时,依赖关系要么位于由构建工具管理的本地工件存储库中(类似于浏览器缓存),要么从远程存储库中下载(无论是公共存储库还是私有存储库,例如Maven Central , Artifactory或Nexus) 。 然后,构建工具根据其作用域将解析出的工件添加到相应的类路径中。 组装构建工件(例如"*.war"
或"*.ear"
档案时,所有必需的依赖项也将得到正确处理和打包。
尽管依赖关系管理似乎是几乎所有构建都必不可少的部分,但并非所有构建工具都为其提供内置支持: Ant和MSBuild缺少此功能,后来Ivy和NuGet在一定程度上解决了这一差距。 但是,与Maven相比,Ivy的采用速度较慢,而NuGet是仅.NET的工具。 随着时间的流逝,Maven工件存储库和Maven Central已经成为分布和共享Java工件的事实上的机制。 对于所有较新的Java构建工具而言,能够使用Maven存储库解析和部署这些资源已成为其“必备”功能。
发行和快照依赖性
如前所述,内部依赖关系通常使用快照版本定义,而外部依赖关系则使用发行版本。 让我们先看一下发行版本,因为它们更容易推论。
发行依赖关系是具有固定版本号的依赖关系 ,例如Groovy发行版的"1.8.6"
版本。 无论构建使用什么工件存储库,并且无论何时尝试查找此依赖项,总是希望它解析出完全相同的工件。 这是发布依赖项的主要原理: “相同版本=相同工件” 。 由于这个事实,一旦发现发布依赖更新,构建工具将不检查发布依赖更新,并且仅在清空本地缓存后才会重新下载工件。 当然,所有这一切都是有道理的,因为我们永远都不会期望找到带有相同版本号的同一个库的不同工件!
快照依赖关系是不同的,因此,处理起来很棘手。 快照依赖项版本以特殊的"-SNAPSHOT"
关键字结尾,例如"3.2.0-SNAPSHOT"
。 此关键字向构建工具发出信号,以通过远程存储库定期检查工件以进行更新; 默认情况下,Maven 每天执行一次此检查。 快照依赖关系的功能,那么,是依靠别人的工作正在进行中(想想“每日构建”):当产品开发移动从版本"X"
到版本"X+1"
的模块版本"X+1-SNAPSHOT"
。
快照相关性不确定性
如果发布依赖关系的主要原则是“相同版本=相同工件” (版本“ X”发布的库,其工件在世界范围内永远相同),则快照依赖关系的原则是“相同版本=不断更新”神器” 。 这种方法的好处是它可以检索频繁的更新,而无需产生非常不切实际的每日发布。 但是,它的缺点是不确定性–在构建脚本中使用快照依赖关系会使得更难知道在特定构建执行过程中使用了哪个版本。 我的"maven-about-plugin"
将文本“ about”文件存储在每个快照工件中,以便更好地标识其来源,例如VCS版本和内部版本号; 这可能会有所帮助,但只能解决一半问题。
作为其定义的移动目标,快照依赖项不允许我们确定我们所依赖的版本,因此很难实现构建的可复制性。 同样,在一系列构建或构建管道中(当完成的构建触发了后续构建的调用时),初始管道步骤产生的工件不一定被关闭的那些消耗,因为它可能会被其他构建过程长时间覆盖,与此同时。
在这种情况下,一种可能的方法是使用时间戳 锁定构建脚本中的依赖项版本,使其成为"3.2.0-20120119.134529-1"
而不是"3.2.0-SNAPSHOT"
。 这有效地使快照依赖关系与发行依赖关系相同,并禁用了自动更新机制,从而即使在没有时间戳的情况下也无法使用最新版本,除非更新了时间戳。
如您所见,可以在有意义的地方使用快照依赖关系,但应谨慎并小剂量进行。 如果可能,最好为每个可重用组件管理一个单独的发行生命周期,并让其客户端使用定期更新的发行依赖关系。
摘要
本文概述了Java构建工具对自动依赖项的管理,并介绍了Maven版本和快照依赖项。 它还解释了快照依赖项的优势如何在构建可复制性和构建管道的背景下值得商bat。
以下博客文章将探讨TeamCity构建链和Artifactory构建隔离,这些构建隔离允许在整个构建链中使用一致,可重现和最新的快照版本,而无需在构建脚本中锁定其时间戳。 还有更多!
参考:来自Goldman ++博客的JCG合作伙伴 Evgeny Goldin的Maven Build Dependencies 。
翻译自: https://www.javacodegeeks.com/2012/05/maven-build-dependencies.html
maven 构建依赖树