首页 文章

在Maven中dependencyManagement和依赖关系之间的差异

提问于
浏览
550

dependencyManagementdependencies 之间有什么区别?我在Apache Maven网站上看过这些文档 . 似乎在 dependencyManagement 下定义的依赖关系可以在其子模块中使用而无需指定版本 .

例如:

父项目(Pro-par)在 dependencyManagement 下定义依赖项:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8</version>
    </dependency>
 </dependencies>
</dependencyManagement>

然后在Pro-par的孩子,我可以使用junit:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </dependency>
 </dependencies>

但是,我想知道是否有必要在父pom中定义junit?为什么不直接在所需的模块中定义它?

9 回答

  • 473

    Maven网站上的documentation非常糟糕 . dependencyManagement所做的只是将您的依赖关系定义(版本,排除等)移动到父pom,然后在子poms中您只需要放置groupId和artifactId . 那个's it (except for parent pom chaining and the like, but that'也不是很复杂 - dependencyManagement胜过父级别的依赖关系 - 但是如果有关于那个或者导入的问题,那么Maven文档会好一些) .

    在阅读了Maven网站上的所有'a','b','c'垃圾并且感到困惑之后,我重新编写了他们的例子 . 因此,如果你有2个项目(proj1和proj2)共享一个共同的依赖项(betaShared),你可以将该依赖项移动到父pom . 当你在这里时,你也可以提升任何其他依赖项(alpha和charlie),但前提是它对你的项目有意义 . 因此,对于前面句子中概述的情况,这里是父pom中具有dependencyManagement的解决方案:

    <!-- ParentProj pom -->
    <project>
      <dependencyManagement>
        <dependencies>
          <dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
            <groupId>alpha</groupId>
            <artifactId>alpha</artifactId>
            <version>1.0</version>
            <exclusions>
              <exclusion>
                <groupId>zebra</groupId>
                <artifactId>zebra</artifactId>
              </exclusion>
            </exclusions>
          </dependency>
          <dependency>
            <groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
            <artifactId>charlie</artifactId>
            <version>1.0</version>
            <type>war</type>
            <scope>runtime</scope>
          </dependency>
          <dependency> <!-- defining betaShared here makes a lot of sense -->
            <groupId>betaShared</groupId>
            <artifactId>betaShared</artifactId>
            <version>1.0</version>
            <type>bar</type>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
    </project>
    
    <!-- Child Proj1 pom -->
    <project>
      <dependencies>
        <dependency>
          <groupId>alpha</groupId>
          <artifactId>alpha</artifactId>  <!-- jar type IS DEFAULT, so no need to specify in child projects -->
        </dependency>
        <dependency>
          <groupId>betaShared</groupId>
          <artifactId>betaShared</artifactId>
          <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
        </dependency>
      </dependencies>
    </project>
    
    <!-- Child Proj2 -->
    <project>
      <dependencies>
        <dependency>
          <groupId>charlie</groupId>
          <artifactId>charlie</artifactId>
          <type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
        </dependency>
        <dependency>
          <groupId>betaShared</groupId> 
          <artifactId>betaShared</artifactId> 
          <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
        </dependency>
      </dependencies>
    </project>
    
  • 42

    我对这个问题的时间已经很晚了,但我认为值得更清楚的回应而不是被接受的回答(这是正确的,但并不强调实际的重要部分,你需要自己推断) .

    在父POM中, <dependencies><dependencyManagement> 之间的主要区别是:

    <dependencies> 部分中指定的工件将始终作为子模块的依赖项包含在内 .

    如果在子模块本身的 <dependencies> 部分中也指定了 <dependencyManagement> 部分中指定的工件,它们将仅包含在子模块中 . 你问为什么这么好?因为您在父项中指定了版本和/或作用域,并且在指定子POM中的依赖项时可以将它们保留 . 这可以帮助您为子模块使用统一版本的依赖项,而无需在每个子模块中指定版本 .

  • 13

    有一些答案概述 <depedencies><dependencyManagement> 标签与maven之间的差异 .

    但是,下面简要阐述的几点很简单:

    • <dependencyManagement> 允许合并在不同模块中使用的所有依赖项(在子pom级别使用) - claritycentral dependency version management

    • <dependencyManagement> 允许根据需要轻松升级/降级依赖项,在其他情况下,需要在每个子级别的pom级别执行此操作 - consistency
      始终导入 <dependencies> 标记中提供的

    • 依赖项,而仅当子pom在其 <dependencies> 标记中具有相应条目时,才会导入父pom中 <dependencyManagement> 处提供的依赖项 .

  • 1

    在我看来,还有一件事情没有得到足够的重点,那就是 unwanted inheritance .

    这是一个增量示例:

    我在 parent pom中声明:

    <dependencies>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>19.0</version>
            </dependency>
    </dependencies>
    

    繁荣!我在 Child AChild BChild C 模块中有它:

    • 由儿童poms继承的implicilty

    • 一个值得管理的地方

    • 无需在儿童poms中重新声明任何内容

    • 如果我愿意,我仍然可以在 Child B 中重新审核并覆盖 version 18.0 .

    但是,如果我最终在 Child C 中不需要 Guava ,以及将来 Child DChild E 模块中都不需要怎么办?

    They will still inherit it and this is undesired! 这就像Java God Object代码气味一样,你从类中继承了一些有用的东西,还有一些不需要的东西 .

    这就是 <dependencyManagement> 发挥作用的地方 . 当您将其添加到父pom时,所有子模块 STOP seeing it . 因此,你是 forced 进入每个需要它的单独模块并再次声明它( Child AChild B ,但没有版本) .

    而且,很明显,你没有为 Child C 这样做,因此你的模块仍然是精益的 .

  • 8

    在父POM中, <dependencies><dependencyManagement> 之间的主要区别在于:

    <dependencies> 部分中指定的工件将始终作为子模块的依赖项包含在内 .

    如果在子模块本身的部分中也指定了子模块,则该部分中指定的工件将仅包含在子模块中 . 你问为什么这么好?因为您在父项中指定了版本和/或作用域,并且在指定子POM中的依赖项时可以将它们保留 . 这可以帮助您为子模块使用统一版本的依赖项,而无需在每个子模块中指定版本 .

  • 42

    就像你说的那样; dependencyManagement 用于将所有依赖关系信息提取到一个公共POM文件中,从而简化了引用子POM文件 .

    当您有多个不想在多个子项目中重新键入的属性时,它会变得很有用 .

    最后, dependencyManagement 可用于定义要在多个项目中使用的工件的标准版本 .

  • 350

    如果依赖项是在顶级pom的dependencyManagement元素中定义的,则子项目不必显式列出依赖项的版本 . 如果子项目确实定义了一个版本,它将覆盖顶级POM的dependencyManagement部分中列出的版本 . 也就是说,dependencyManagement版本仅在子项未直接声明版本时使用 .

  • 9

    在Eclipse中, dependencyManagement 还有一个功能 . 如果在没有它的情况下使用 dependencies ,则会在pom文件中注意到未发现的依赖项 . 如果使用 dependencyManagement ,则未解决的依赖关系在pom文件中仍未被注意,并且错误仅出现在java文件中 . (进口等...)

  • 3

    Dependency Management允许合并和集中管理依赖项版本,而无需添加所有子项继承的依赖项 . 当您拥有继承公共父级的 a set of projects (即多个)时,这尤其有用 .

    dependencyManagement 的另一个非常重要的用例是控制传递依赖中使用的工件版本 . 没有一个例子,这很难解释 . 幸运的是,这在文档中有说明 .

相关问题