1. 强制版本(Highest Priority)

  • <dependency> 中直接指定的版本优先级最高。
  • 例如:
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>example-artifact</artifactId>
        <version>1.0.0</version> <!-- 强制指定版本 -->
    </dependency>
    
    即使其他依赖传递了不同版本,此处的 1.0.0 会优先使用。

2. 依赖管理(Dependency Management)

  • <dependencyManagement> 中定义的版本优先级次高。
  • 例如:
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>example-artifact</artifactId>
                <version>2.0.0</version> <!-- 通过 dependencyManagement 指定版本 -->
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    即使传递依赖有其他版本,2.0.0 会被优先使用。

3. 父 POM 的依赖管理

  • 如果项目继承了父 POM,父 POM 的 <dependencyManagement> 会覆盖子模块的依赖版本。
  • 除非子模块明确指定了不同版本,否则父 POM 的版本优先级高于传递依赖。

4. 最近定义优先(Nearest Wins)

  • 在依赖树中,路径最短的依赖版本优先级较高。
  • 例如:
    • 项目直接依赖 A 和 B。
    • A 依赖 C 1.0。
    • B 依赖 D,而 D 依赖 C 2.0。
    • 由于 A 到 C 的路径更短,C 1.0 会被使用。

5. 最先声明优先(First Declaration Wins)

  • 如果两个依赖路径长度相同,POM 文件中先声明的依赖版本优先级较高。
  • 例如:
    • 项目直接依赖 A 和 B。
    • A 依赖 C 1.0。
    • B 依赖 C 2.0。
    • 如果 A 在 POM 中先声明,则 C 1.0 会被使用。

6. 传递依赖(Transitive Dependencies)

  • 如果以上规则都未生效,Maven 会使用传递依赖的版本。
  • 传递依赖的版本优先级最低。

7. 排除依赖(Exclusions)

  • 使用 <exclusions> 可以排除特定依赖,从而间接影响优先级。
  • 例如:
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>example-artifact</artifactId>
        <version>1.0.0</version>
        <exclusions>
            <exclusion>
                <groupId>com.other</groupId>
                <artifactId>other-artifact</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    排除依赖后,可能会使用其他路径中的版本。

优先级总结(从高到低)

  1. 强制版本(在 <dependency> 中直接指定)
  2. 依赖管理(在 <dependencyManagement> 中指定)
  3. 父 POM 的依赖管理
  4. 最近定义优先(路径最短的依赖)
  5. 最先声明优先(POM 中先声明的依赖)
  6. 传递依赖(默认的依赖版本)
  7. 排除依赖(通过排除间接影响优先级)

示例场景

假设有以下依赖关系:

  • 项目直接依赖 A 和 B。
  • A 依赖 C 1.0。
  • B 依赖 C 2.0。
  • 父 POM 的 <dependencyManagement> 指定 C 3.0。
  • 项目中通过 <dependency> 强制指定 C 4.0。

最终优先级:

  1. 强制版本 C 4.0 被使用(最高优先级)。
  2. 如果没有强制版本,则使用依赖管理中的 C 3.0。
  3. 如果没有依赖管理,则使用路径最短的依赖(A 的 C 1.0 或 B 的 C 2.0)。
  4. 如果路径长度相同,则使用 POM 中先声明的依赖版本。