maven 依赖关系管理和范围

bogh5gae  于 2023-02-07  发布在  Maven
关注(0)|答案(5)|浏览(202)

我通常在parent-project/pom.xml中放置一个<dependencyManagement>节,这个<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>部分更好(就像这篇文章一样)?为什么?
这个问题有没有明确的答案?

uajslkp6

uajslkp61#

派对来晚了点,不过我也要说两句。
我最近遇到了一个很难调试的问题。
我有一个用于管理多个项目依赖关系的父pom,我把它设置为包含了所有常见的依赖关系,包括groupIdartifactIdversion和 * 最常见的scope
我的想法是,如果它符合 * 最常见的scope
,我就不必在每个项目的实际依赖项部分中包含范围。
当其中某些依赖项显示为可传递依赖项时,就会出现问题。例如,如果:

  • A在编译范围内依赖于B。
  • B在编译范围内依赖于C。
  • C设置为在父项的dependencyManagement中提供。

然后A对C的传递依赖被确定为被提供,我不确定这是否有意义,但这确实令人困惑。
不管怎样,保存你自己的麻烦吧,把scope从你的dependencyManagement中留出来。

cyvaqqii

cyvaqqii2#

dependencyManagement仅用于定义所有项目子模块的依赖性版本,本节中唯一相关的范围是BOM的import
范围必须在dependencies节中定义。

  • (对于给定的依赖关系,它确定使用上下文。它允许仅在需要执行时包含依赖关系。例如,ear将不会与Java-ee依赖关系(作用域provided)一起打包,因为它将在目标服务器上找到它们。)*
    **[编辑]

第一条语句有一个异常,dependencyManagement节中的作用域provided将覆盖dependencies节中定义的作用域。请参见DependencyManagement to force scope

92dk7w1h

92dk7w1h3#

与其他答案一样,最佳做法是从dependencyManagement中排除作用域,并在定义依赖项时显式指定它。您希望在不同的作用域中使用同一依赖项的不同版本的情况很少见,例如,编译应用时使用一个版本,运行时使用另一个版本--我能想到的唯一情况是,您希望针对库的不同版本显式地运行测试,以防用户使用该版本而不是您指定的版本。
如果你在dependencyManagement中定义了作用域,它会限制那个版本只能在定义的作用域中使用--所以任何其他的作用域都会选择一个随机版本的依赖项。昨天当我们在dependencyManagement中定义junit4.12的时候,我遇到了这个问题,但是我们的公共测试框架模块使用的是junit的编译作用域,所以它选择了版本4.8.2。

6ljaweal

6ljaweal4#

对于任何作用域,向依赖项管理添加单个依赖项都没有任何好处。您所拥有的只是复制。如果希望版本可配置,请添加一个属性并在依赖项中使用它:

<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>
....
62o28rlo

62o28rlo5#

超级晚的聚会,但最新的maven有非常明确的文档传递依赖范围和dependencyManagement细节,包括一个例子.https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-scope从文档我们可以看到:
1.当可传递作用域不同时,有优先规则控制哪一个将被应用。2乍一看,规则表是复杂的,但它对大多数情况是有常识的。
1.文档中专门有一个dependency scope和dependencyManagement合并案例的示例,最终遵循1中的规则。
作为结论,建议以最“常见”的方式包含作用域。如果存在传递性、冲突性或陷入困境的情况,我们需要仔细检查优先级规则。

相关问题