Maven从伟大的父母那里获取依赖版本,而不是我们父母的依赖管理

下面显示了我的POM的层次结构。

你可以看到我们有一个公司的父亲pom春季启动项目。 这个POM有spring-boot-starter作为它的父级,它导入我们自己的依赖管理BOM。

[INFO] --- hierarchy-maven-plugin:1.4:tree (default-cli) @ user-service --- [INFO] PARENT com.MY_COMPANY.platform:user:3.20.14-SNAPSHOT [INFO] PARENT com.MY_COMPANY.platform:spring-boot-parent:3.20.12-SNAPSHOT [INFO] PARENT org.springframework.boot:spring-boot-starter-parent:1.5.12.RELEASE [INFO] PARENT org.springframework.boot:spring-boot-dependencies:1.5.12.RELEASE <<<< This pom defines assertJ 2.x [INFO] [ other imports ] [INFO] IMPORT com.MY_COMPANY:dependencyManagementBase:2.23.14-SNAPSHOT <<<<<<<<<<<< This pom defines assertJ 3.x [INFO] IMPORT com.MY_COMPANY.platform:platform-dependency-management:1.20.7 [INFO] ------------------------------------------------------------------------ 

为了专注于特定的,我们在依赖管理中定义AssertJ 3; 然而,spring-boot-dependencies定义了AssertJ 2.与assertJ没什么关系,但还有其他类似Mongo-Java-Driver的鱼没有拿起我们的版本。

Maven如何在这里选择优先权? 为什么我们的依赖管理不会战胜远祖的依赖管理?

我还注意到,如果我将AssertJ作为MY_COMPANY.platform:spring-boot-parent的依赖项添加,它也不会在我们的依赖管理中使用该版本(所以我现在只保留它,所以层次结构下显微镜更短)。

编辑 – 添加缩写的POM

com.MY_COMPANY.platform:弹簧引导父

   4.0.0 com.MYCOMPANY.platform spring-boot-parent 3.20.12-SNAPSHOT pom  3.0.4   org.springframework.boot spring-boot-starter-parent 1.5.12.RELEASE   2.23.13    org.assertj assertj-core test      com.MYCOMPANY dependencyManagementBase ${MYCOMPANYdependencymanagement.version} pom import     

com.MY_COMPANY:dependencyManagementBase

   4.0.0 com.MYCOMPANY dependencyManagementBase 2.23.13 pom  spring-dep-man   3.5.2     org.assertj assertj-core ${org.assertj-core.version} test     

**编辑2 – 添加显示不同版本的详细层次结构**

 ~/p/springbootparentpom> mvn hierarchy:tree -Dlevel=full [INFO] --- hierarchy-maven-plugin:1.4:tree (default-cli) @ spring-boot-parent --- [INFO] Displaying hierarchy. [INFO] PARENT org.springframework.boot:spring-boot-starter-parent:1.5.12.RELEASE [INFO] PARENT org.springframework.boot:spring-boot-dependencies:1.5.12.RELEASE [INFO] DEP_MANAGEMENT ........ [INFO] DEP_MANAGEMENT org.assertj:assertj-core:2.6.0 [INFO] [ ... Many DEP_MAN and IMPORT ... ] [INFO] IMPORT com.MYCOMPANY:dependencyManagementBase:2.23.14-SNAPSHOT [INFO] DEP_MANAGEMENT ........ [INFO] DEP_MANAGEMENT org.assertj:assertj-core:3.5.2 [INFO] DEP_MANAGEMENT ........ 

我的猜测是它抓住了最近的。

依赖关系中介 – 确定在遇到多个版本的工件时将使用哪个版本的依赖关系。 目前,Maven 2.0仅支持使用“最近定义”,这意味着它将在依赖树中使用与项目最接近的依赖项版本。 您可以通过在项目的POM中明确声明它来保证版本。 请注意,如果两个依赖关系版本在依赖关系树中处于相同的深度,则直到Maven 2.0.8没有定义哪一个会赢,但是自Maven 2.0.9开始,它就是声明中的顺序:第一个声明获胜。

我为这样的东西做的是转到给定项目的IDE的依赖项部分。 它向我展示了所有依赖项,版本以及它来自何处(有关示例,请参阅下面附加图片的弹出窗口底部)。

在此处输入图像描述

问题是您的项目不依赖于父项进行依赖项管理,而是依赖于导入的项目。 Maven依赖关系层次结构不起作用。 可能最好的解决方案是将’parent spring-boot-starter-parent’声明移动到MY_COMPANY:dependencyManagementBase项目中。 然后更改com.MYCOMPANY.platform中的父声明以指向dependencyManagementBase项目。 这样你就会有一个清晰的inheritance层次结构。

您目前拥有的并不真正使用依赖关系管理。 即如果您要将dependencyManagementBase项目中的“dependecyManagement”部分更改为“dependency”,您将获得相同的结果。

似乎没有人有答案。 所以我只想回答我的发现。

鉴于OP不起作用。 我的下一个策略是IMPORT spring-boot-starter-parent和spring-boot-dependency POM,因为我不能将它们用作父项。

然而,这有它自己的行为。

我发现如果我的依赖管理看起来像这样,我的版本赢了:

    com.mycompany dependency-management-slim 2.23.14-SNAPSHOT pom import  org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import   org.springframework.boot spring-boot-starter-parent ${spring-boot.version} pom import    

但是,我决定将自定义代码与我的spring-boot模仿pom分开。 所以为了保持优先权,我认为我必须这样做:

 service-root -> only import my-dependency-management ^-- spring-boot-parent -> mimick and import spring-boot-starter-parent ^-- service-parent -> has our common dependencies and profiles ^-- service-impl - code 

但是,这没有用; spring-boot版本覆盖了我们的自定义版本。 所以我不得不这样做:

 root-parent -> nothing ^-- spring-boot-parent -> mimick and import spring-boot-starter-parent ^-- service-parent -> import my-dependency-management ^-- service-impl - code 

结论

  • 如果在SAME pom中导入多个依赖关系管理,则第一个管理版本获胜。
  • 如果您要导入多个poms,则导入的最后一个获胜。
  • 如果父级定义了依赖关系管理,并且定义了各个依赖关系,则不能使用依赖关系管理覆盖它们(这是原始问题)。

¯\ _(ツ)_ /¯