在部分声明依赖,即使依赖项没有在任何地方使用?

我们正在使用maven 2.1.0。 我有多个完全独立的模块,但仍然有许多常见的依赖项。 像log4J,但有些模块不需要它。 我想知道在部分中的一个父文件中声明所有公共依赖项是否是一个好主意,还是有更好的方法来处理它?

关于后续问题。 如果我在父项的部分中声明Log4J并且子项目不使用它,那么它是否会包含在内?

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

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

它也是有用的(如果有超过1-2个开发人员一起工作)来设置内部存储库(如Artifactory )并在内部使用它。 这使得处理不在公共存储库中的库变得更容易(只需将其添加到您的内部存储库!)并且您还可以使用构建工具来推送您自己的代码的构建,以便其他人可以使用这些模块而无需检出代码(在大型项目中有用)

如果您有父项目,则可以在父pom的dependencyManagement部分中声明所有依赖项及其版本。 这并不意味着所有项目都将使用所有这些依赖项,这意味着如果项目确实声明了依赖项,它将inheritance配置,因此它只需要声明依赖项的groupId和artifactId。 您甚至可以在父类的dependencyManagement中声明子项目而不引入循环。

请注意,您也可以通过在pluginManagement部分中声明插件来执行与插件类似的操作。 这意味着声明该插件的任何子代都将inheritance该配置。

例如,如果您有4个项目, parentcoreuiutils ,则可以在父项中声明所有外部依赖项和内部项目版本。 然后子项目inheritance它们声明的任何依赖项的配置。 如果所有模块都具有相同的版本,则甚至可以将这些模块声明为父级中的属性。

示例父母如下:

  4.0.0 name.seller.rich parent 1.0.0 pom    commons-io commons-io 1.4   name.seller.rich ui ${project.version}   name.seller.rich core ${project.version}   name.seller.rich utils ${project.version}     utils core ui   

utils,core和ui项目inheritance了所有相关版本。 utils的:

  4.0.0 name.seller.rich utils   parent name.seller.rich 1.0.0    commons-io commons-io    

核心:

  4.0.0 name.seller.rich core  parent name.seller.rich 1.0.0    name.seller.rich utils   

用户界面:

  4.0.0 name.seller.rich ui  parent name.seller.rich 1.0.0    name.seller.rich core    

我写了一份最佳实践清单。 这是最重要的。

  • 始终使用maven-enforcer-plugin
    • 实施依赖性收敛
      • 否则你可能依赖于两个不同的jar,它们都依赖于log4j。 在编译时使用哪一个取决于您不应该记住的一组规则。 它们都可以(!)作为传递依赖项导出。
    • 需要插件版本 (适用于所有插件,甚至是内置插件)
      • 在父pom中的pluginManagement中定义它们以定义版本
      • 否则,新版本的maven-surefire-plugin可能会破坏您的构建
  • 在父pom中使用dependencyManagement可以在所有模块中一致地使用版本
  • 定期运行mvn依赖:分析
    • 您可能会在编译时直接依赖于传递依赖关系。 如果是这样,使用您需要的版本将其添加到您的pom非常重要。 这与enforcer插件很好地配合。
    • 您可能正在声明不使用的额外依赖项。 这在100%的时间内都无法正常工作,特别是对于设计为具有可选部分的库(即slf4j-api被正确检测到,但slf4j-log4j12失败)。

关于的后续问题。 如果我在父项的部分中声明Log4J并且子项目不使用它,那么它是否会被包括在内?

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

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

在这种情况下,是和否。

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

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

我们为所有项目使用具有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. 将foo.jar版本1.1声明为B中的依赖项,使得看起来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。

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