1. 概述

本文将快速介绍 Maven 如何利用 BOM(Bill of Materials)机制管理依赖版本。Maven 作为基于 POM(Project Object Model)概念的工具,通过 BOM 实现依赖版本的集中控制。

关于 Maven 的更多细节,可参考 Apache Maven 教程

2. 依赖管理核心概念

要理解 BOM 的作用,需先掌握几个基础概念:

2.1 什么是 Maven POM?

Maven POM 是一个 XML 文件,包含项目信息和配置,用于:

  • 导入依赖
  • 构建项目
  • 管理生命周期

2.2 什么是 Maven BOM?

BOM(Bill of Materials)是一种特殊的 POM 文件,核心作用是集中管理项目依赖的版本。它提供:

  • 统一的版本定义中心
  • 依赖版本更新的唯一入口
  • 模块化依赖管理的灵活性(添加依赖时无需指定版本)

2.3 传递依赖

Maven 会自动解析 pom.xml 中依赖所需的库,并递归引入所有层级的依赖。⚠️ 当不同路径引用同一依赖的不同版本时,会产生冲突:

A -> B -> C -> D 1.4  and  A -> E -> D 1.0

冲突解决原则:依赖调解(Dependency Mediation)
采用"最近定义优先"策略:

  • 项目 A 依赖 B 和 E
  • B 和 E 分别依赖 D 1.4 和 D 1.0
  • 最终使用 D 1.0(因为路径 A->E->D 更短)

✅ 解决冲突的两种方法:

  1. 显式声明:在项目 POM 中直接指定版本(如强制使用 D 1.4)
  2. 依赖管理:通过 dependencyManagement 统一控制(后文详述)

2.4 依赖管理机制

依赖管理本质是集中化依赖信息的机制。当多个项目继承同一父 POM 时,可将所有依赖信息定义在共享的 BOM 文件中:

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Baeldung-BOM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>BaelDung-BOM</name>
    <description>parent pom</description>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>test</groupId>
                <artifactId>a</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>test</groupId>
                <artifactId>b</artifactId>
                <version>1.0</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>test</groupId>
                <artifactId>c</artifactId>
                <version>1.0</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

BOM 本质是包含 dependencyManagement 的标准 POM 文件。

2.5 使用 BOM 文件

有两种方式在项目中使用 BOM:

方式一:继承父 BOM

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    <parent>
        <groupId>baeldung</groupId>
        <artifactId>Baeldung-BOM</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
</project>

方式二:导入 BOM(推荐大型项目)

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>baeldung</groupId>
                <artifactId>Baeldung-BOM</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

❌ 继承方式限制:只能有一个父 POM
✅ 导入方式优势:可导入多个 BOM 文件

2.6 覆盖 BOM 依赖

版本优先级规则(从高到低):

  1. 项目 POM 中的显式声明
  2. 父项目中的版本定义
  3. 导入的 BOM 版本(按导入顺序)
  4. 依赖调解机制

⚠️ 覆盖场景:

  • 显式覆盖:在项目 POM 中直接声明依赖版本
  • 多 BOM 冲突:当多个 BOM 定义同一依赖不同版本时,先导入的 BOM 生效

3. Spring BOM 实践

第三方库或 Spring 项目可能引入旧版本的传递依赖,导致意外问题。通过 Spring BOM 可统一版本:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>5.3.27</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

引入 BOM 后,添加 Spring 依赖无需指定版本:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
<dependencies>

4. 总结

本文介绍了 Maven BOM 的核心概念及实践要点:

  • BOM 通过 dependencyManagement 集中管理依赖版本
  • 支持继承和导入两种使用方式(大型项目推荐导入)
  • Spring BOM 解决了依赖版本不一致问题
  • 版本覆盖需遵循优先级规则

文中示例代码可在 GitHub 获取。


原始标题:Spring with Maven BOM