代码之家  ›  专栏  ›  技术社区  ›  Mike Pone

在<DependencyManagement>部分中声明依赖项,即使依赖项未在任何地方使用?

  •  19
  • Mike Pone  · 技术社区  · 15 年前

    我们使用的是Maven 2.1.0。我有多个完全独立的模块,但仍然有许多共同的依赖项。像log4j,但有些模块不需要它。我想知道在 <dependencyManagement> 还是有更好的方法来处理这个问题?

    关于的后续问题 <依赖管理> . 如果我在 <依赖管理> 父项目和子项目的部分不使用它,是否仍将其包括在内?

    6 回复  |  直到 11 年前
        1
  •  8
  •   Kris    15 年前

    每个模块都应该有自己的POM,并在其中声明自己的依赖项。这不仅跟踪外部依赖项,还跟踪内部依赖项。

    当你使用Maven来构建一个项目时,它会将整个项目分类。因此,如果许多模块(可能全部)依赖于log4j,那么它将只包含一次。如果您的模块依赖于不同版本的log4j,则会出现一些问题,但这种方法通常可以正常工作。

    建立一个内部存储库(如 Artifactory )在内部使用。它使处理不在公共回购中的库更加容易(只需将其添加到内部回购中!)您还可以使用构建工具将您自己的代码的构建推送到那里,这样其他人就可以在不签出代码的情况下使用模块(在大型项目中很有用)。

        2
  •  33
  •   Rich Seller    15 年前

    如果有父项目,可以在父POM的DependencyManagement部分声明所有依赖项及其版本。这个 意味着所有项目都将使用所有这些依赖项,这意味着如果一个项目声明了依赖项,它将继承配置,因此它只需要声明依赖项的groupid和artifactid。甚至可以在父级的DependencyManagement中声明子项目,而无需引入循环。

    注意,通过在pluginManagement部分声明插件,您也可以对插件执行类似的操作。这意味着声明插件的任何子级都将继承配置。

    例如,如果您有4个项目, 起源 , 核心 , 用户界面 乌迪斯 ,您可以在父级中声明所有外部依赖项和内部项目版本。然后,子项目将继承它们声明的任何依赖项的配置。如果所有模块的版本都相同,那么甚至可以在父级中将它们声明为属性。

    父级示例如下:

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>name.seller.rich</groupId>
      <artifactId>parent</artifactId>
      <version>1.0.0</version>
      <packaging>pom</packaging>
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.4</version>
          </dependency>
          <dependency>
            <groupId>name.seller.rich</groupId>
            <artifactId>ui</artifactId>
          <version>${project.version}</version>
          </dependency>
          <dependency>
            <groupId>name.seller.rich</groupId>
            <artifactId>core</artifactId>
            <version>${project.version}</version>
          </dependency>
          <dependency>
            <groupId>name.seller.rich</groupId>
            <artifactId>utils</artifactId>
            <version>${project.version}</version>
          </dependency>
        </dependencies>
      </dependencyManagement>
      <modules>
        <module>utils</module>
        <module>core</module>
        <module>ui</module>
      </modules>
    </project>
    

    而utils、core和ui项目继承了所有相关的版本。 UTILS:

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>name.seller.rich</groupId>
      <artifactId>utils</artifactId>
      <!--note version not declared as it is inherited-->
      <parent>
        <artifactId>parent</artifactId>
        <groupId>name.seller.rich</groupId>
        <version>1.0.0</version>
      </parent>
      <dependencies>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
        </dependency>
      </dependencies>
    </project>
    

    核心:

    <project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>name.seller.rich</groupId>
    <artifactId>core</artifactId>
    <parent>
      <artifactId>parent</artifactId>
      <groupId>name.seller.rich</groupId>
      <version>1.0.0</version>
    </parent>
    <dependencies>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>utils</artifactId>
      </dependency>
    </dependencies>
    

    用户界面:

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>name.seller.rich</groupId>
      <artifactId>ui</artifactId>
      <parent>
        <artifactId>parent</artifactId>
        <groupId>name.seller.rich</groupId>
        <version>1.0.0</version>
      </parent>
      <dependencies>
        <dependency>
          <groupId>name.seller.rich</groupId>
          <artifactId>core</artifactId>
        </dependency>
      </dependencies>
    </project>
    
        3
  •  16
  •   Craig P. Motlin    13 年前

    我写了一份清单 best practices . 这里是最重要的。

    • 总是使用 maven-enforcer-plugin
      • 强制执行 dependency convergence
        • 否则,您可能依赖于两个不同的jar,这两个jar都依赖于log4j。哪个jar在编译时使用,取决于一组您不必记住的规则。它们都可以!!)导出为可传递的依赖项。
      • 要求 plugin versions (适用于所有插件,甚至内置插件)
        • 在父pom的pluginmanagement中定义它们以定义版本
        • 否则,Maven Surefire插件的新版本可能会破坏您的构建
    • 在父POM中使用DependencyManagement在所有模块中一致地使用版本
    • 定期运行 mvn dependency:analyze
      • 有可能您在编译时得到了一个直接依赖的依赖关系。如果是这样的话,用你需要的版本把它添加到你的POM中是很重要的。这与Enforcer插件配合得很好。
      • 您可能正在声明不使用的额外依赖项。这在100%的时间内都不能正常工作,特别是对于设计为具有可选部分的库(即SLF4J API被正确检测,但SLF4J-log4j12失败)。
        4
  •  1
  •   DavidValeri    15 年前

    关于的后续问题。如果我在父项目部分声明log4j,而子项目不使用它,它是否仍将包含在内?

    不需要。依赖关系管理只设置默认版本和可能的范围(我已经看到这两个版本似乎都是继承的,并且似乎没有被继承,所以您需要自己查找这个版本)。要在子模块中包含依赖项,需要将其声明为模块的依赖项并省略version元素。您可以覆盖子模块中的默认值,只需在子模块的pom的dependency元素中包含版本号即可。

    我有多个完全独立的模块,但仍然有许多共同的依赖关系。

    在这种情况下,是和否。

    对于作为一个统一项目一起构建、版本化和部署的模块,例如组成单个Web应用程序的模块,肯定是的。当您决定转移到依赖项的新版本时,您希望减轻在多个POM中更改版本的头疼。当需要排除某些可传递的依赖项时,它还可以保存您的工作。如果您在部分中声明依赖项及其排除项,则不必在多个POM中维护排除项。

    对于不直接相关但在公司内单个团队内构建的模块,您可能需要考虑为通用库(如测试实用程序、日志记录实用程序等)声明默认版本,以便让团队使用您定义为最佳实践一部分的工具的标准版本。记住,当您标准化一组新的公共库时,您总是可以增加超级POM的版本。在标准化库和工具以及特定于项目的库和工具之间划一条线,这取决于您自己,但是您的团队应该很容易找到。

        5
  •  1
  •   Dwight Shih    13 年前

    对于我们的所有项目,我们使用一个具有DependencyManagement块的公共父级。当我们将更多的项目移入maven中时,这就开始崩溃了——如果一个项目需要不同的版本,那么我们要么将它声明为所有子项的依赖项,要么显式定义每个相关子项的版本。

    我们正在尝试一个模型,将DependencyManagement从我们的共同母公司中分离出来,然后将我们的企业DependencyManagement POM导入到顶级项目POM中。这允许我们有选择地定义覆盖公司默认值的项目默认值。

    以下是原始场景:

    A   defines version 1.0 of foo.jar as the corporate default
    B   child of A
    C1, C2, C3  children of B
    D1, D2, D3 children of C1, C2, C3 respectively
    

    如果d1和d2需要foo.jar的1.1版本,那么我们的选择是:

    1. 在b中将foo.jar版本1.1声明为依赖项,使c1、c2、c3和d3看起来也依赖于版本1.1。
    2. 将foo.jar版本1.1声明为d1和d2中的依赖项,将依赖项声明移动到项目层次结构中更深层的多个位置。

    以下是我们正在尝试的内容:

    A   defines version 1.0 of foo.jar as the corporate default
    B   dependencyManagement: imports A, declares a default of foo.jar version 1.1
    C1, C2, C3  children of B
    D1, D2, D3 children of C1, C2, C3 respectively
    

    现在,d1和d2只声明了对foo.jar的依赖,并从b的dependencyManagement块中获取1.1版。

        6
  •  0
  •   MikeJ    15 年前

    在一个多模块项目中,我在父pom.xml的元素中放置任何公共依赖项。不过,如果模块与同一个项目无关,我不确定这是否是最佳实践。