依赖管理和范围
Posted
技术标签:
【中文标题】依赖管理和范围【英文标题】:dependencyManagement and scope 【发布时间】:2013-02-19 16:57:13 【问题描述】:我通常将<dependencyManagement>
部分放在parent-project/pom.xml
中。这个<dependencyManagement>
部分包含我的子模块的所有依赖项的声明和版本(即没有<scope>
元素):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</dependencyManagement>
在所有子模块(即 moduleX/pom.xml)中,我有:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
显然,在此示例中,我为同一个依赖项重复<scope>test</scope>
多次(在每个需要 junit 的子模块中一次)。
我的问题是:
关于<scope>
声明的最佳实践是什么?
把它放在<dependencyManagement>
中会更好吗?
还是将它放在子模块的<dependencies>
部分更好(就像在这篇文章中一样)?为什么?
这个问题有确定的答案吗?
【问题讨论】:
【参考方案1】:聚会有点晚了,但我会加两分钱。
我最近遇到了一个非常难以调试的问题。
我有一个父 pom 用于管理跨多个项目的依赖项。我设置了它们之间常见的所有依赖项,包括groupId
、artifactId
、version
和最常见的scope
。
我的想法是,如果它符合最常见的scope
,我就不必在每个项目的实际依赖部分中包含范围。
当其中一些依赖项显示为传递依赖项时,就会出现问题。例如,如果:
dependencyManagement
中提供。
那么确定提供了A对C的传递依赖。我不确定这是否有意义,但这确实令人困惑。
无论如何,省去你的麻烦,把scope
从你的dependencyManagement
中去掉。
【讨论】:
这很有意义,但没有很好的记录,请参阅maven.40175.n5.nabble.com/…,我在下面编辑我的答案【参考方案2】:dependencyManagement
只是在这里定义所有项目子模块的依赖版本,本节中唯一相关的范围是 import
用于 BOM。
必须在dependencies
部分中定义范围。
(对于给定的依赖,它决定了使用上下文。它只允许在需要执行时包含依赖。例如,ear 不会与 Java-ee 依赖打包在一起(范围 provided
)因为它会在目标服务器上找到它们。)
[编辑]
第一条语句有一个异常,dependencyManagement
部分中的范围 provided
将覆盖 dependencies
部分中定义的范围。见DependencyManagement to force scope
【讨论】:
“本节中唯一相关的范围是导入”是否意味着如果我将范围test
放在 dependendcyManagement
中:它没有效果?
事实上,我似乎并不完全正确。 maven.40175.n5.nabble.com/…dependencyManagement
范围有兴趣【参考方案3】:
与其他答案一样,最佳实践是从dependencyManagement 中排除范围,并在定义依赖项时明确指定它。极少数情况下,您希望在不同范围内使用相同依赖项的不同版本,例如,在编译应用程序时使用一个版本,而在运行应用程序时使用不同版本——我能想到的唯一情况是您想显式运行您的测试不同版本的库,以防用户使用该版本而不是您指定的版本。
如果您在dependencyManagement 中定义范围,它将将该版本的使用限制为仅定义的范围——因此任何其他范围都将选择依赖项的随机版本。我昨天在dependencyManagement中定义了junit 4.12时遇到了这个问题,但是我们的通用测试框架模块使用的是带有编译范围的junit,所以它选择了4.8.2版本。
【讨论】:
【参考方案4】:对于任何范围,将单个依赖项添加到依赖项管理中没有任何好处。你所拥有的只是复制品。如果您希望版本可配置,请添加一个属性并在您的依赖项中使用它:
<properties>
<junit.version>4.10</junit.version>
...
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>$junit.version</version>
</dependency>
</dependencies>
但是,在某些情况下,依赖管理会大放异彩 - 当您使用 boms
来编排更大的工件集合的版本时,例如使用特定版本的 Java EE 实现:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-javaee-6.0-with-tools</artifactId>
<version>$javaee6.with.tools.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
....
【讨论】:
dependencyManagement(即使只有一个依赖项)是定义工件版本的唯一位置。在我看来,这唯一的事实就足以使用它。使用属性很有用,因为您有多个始终具有相同 versionId 的工件(例如 spring 模块) 使用dependencyManagement 的另一个原因是集中排除不需要的传递依赖项。 使用版本属性的另一个原因是,您可以使用mvn versions:display-property-updates
快速检查依赖版本更新——只要您注意以artifactId.version
模式命名您的版本属性以上是关于依赖管理和范围的主要内容,如果未能解决你的问题,请参考以下文章
04_项目一众筹00_05Maven依赖概念,依赖范围依赖传递性依赖的原则:解决jar包冲突依赖排除统一版本管理
maven课程 项目管理利器-maven 3-7 maven依赖范围 2星
Android Gradle 插件Android 依赖管理 ③ ( dependencies 依赖配置 | Project#dependencies 函数分析 | 自定义依赖配置 )
Maven01_05_compile和test依赖范围Maven的一些依赖情况依赖冲突如果出现冲突就会采取就近原则可选依赖(optional)排除依赖(exclusions)