Zane Blog

Spring Boot Maven 依赖与插件管理:从 Parent 到 BOM 的完整机制

2026-01-07
springboot
maven
最后更新:2026-01-07
13分钟
2435字

Spring Boot Maven 依赖与插件管理:从 Parent 到 BOM 的完整机制

新建 Spring Boot 项目时,发现 Maven 依赖配置存在多个相似概念,产生研究的兴趣。

一、Maven 基础机制

1.1 Maven 依赖分类

Maven 依赖按 packaging 类型分为两大类:

代码包 (有 .class 文件):

packaging全称产物使用场景示例
jarJava Archive.jar普通代码库、工具类spring-core, commons-lang3
warWeb Application Archive.warWeb 应用,部署到 Tomcatmy-webapp
earEnterprise Application Archive.earJ2EE 企业应用my-enterprise

构建描述文件 (没有代码):

类型packaging特征作用示例
聚合 POMpom<modules>管理多个子模块多模块父项目
父 POMpom<dependencyManagement> + <pluginManagement>子模块继承配置spring-boot-starter-parent
BOMpom只有 <dependencyManagement>纯版本字典spring-boot-dependencies
Starter POMpom<dependencies>依赖集合的”便利包”spring-boot-starter-web

快速判断方法:

看本地仓库 ~/.m2/repository/:
├── xxx-1.0.0.jar → 代码包
├── xxx-1.0.0.war → Web 应用
└── xxx-1.0.0.pom → 构建描述文件 (无代码)

1.2 parent 标签 (继承机制)

作用: 让当前 POM 继承另一个 POM 的配置

公式:

parent = 继承配置
├── 继承依赖版本 (dependencyManagement)
├── 继承插件配置 (pluginManagement)
├── 继承属性定义 (properties)
└── 继承其他配置

示例:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>

限制: Maven 单继承,一个 POM 只能有一个 <parent>

1.3 dependencyManagement 标签 (版本管理)

作用: 声明依赖版本号,但不引入依赖

公式:

dependencyManagement = 菜单 (声明版本号,不引入)
dependencies = 点菜 (真正引入 jar 包)

区别:

特性dependencyManagementdependencies
作用声明版本号真正引入依赖
下载 jar❌ 不下载✅ 下载
类比餐厅菜单向服务员点菜

示例:

<dependencyManagement>
<dependencies>
<!-- 声明版本: spring-boot-starter-web 使用 3.2.0 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 真正引入: 无需写版本号,继承上面的 3.2.0 -->
<dependency>
<groupId>org.springframework.boot</groupId>
3 collapsed lines
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

1.4 pluginManagement 标签 (插件管理)

作用: 声明插件版本和配置,但不执行插件

公式:

pluginManagement = 插件菜单 (声明版本和配置)
plugins = 引入插件 (真正执行)

区别:

特性pluginManagementplugins
作用声明插件版本和配置真正引入并执行插件
执行插件❌ 不执行✅ 执行
使用位置通常在父 POM子 POM 继承或独立使用

示例:

<!-- 父 POM -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
12 collapsed lines
</build>
<!-- 子 POM -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- 无需写 version 和 configuration,继承父 POM -->
</plugin>
</plugins>
</build>

1.5 三个核心标签对比

管理对象对比:

标签管理对象作用Maven 单继承限制
<parent>整个 POM继承所有配置只能有一个
<dependencyManagement>依赖版本声明版本号可导入多个 BOM
<pluginManagement>插件声明插件配置可定义多个

使用场景对比:

场景parentdependencyManagementpluginManagement
继承父项目配置--
统一依赖版本✅ (通过继承)✅ (通过 import)-
统一插件配置✅ (通过继承)-✅ (通过继承)
多 BOM 共存❌ (单继承)✅ (import scope)-

二、Spring Boot 核心概念

2.1 spring-boot-starter-parent vs spring-boot-starter

公式:

spring-boot-starter-parent = 规则书(无代码)
spring-boot-starter = 地基(核心代码集合)
spring-boot-starter-web = 地基 + 房子(Web能力)

真相: Parent 的继承链

你的项目
↓ 继承
spring-boot-starter-parent
↓ 继承
spring-boot-dependencies (BOM)
(提供 500+ 依赖的版本号)

关键洞察:

spring-boot-starter-parent 本身继承自 spring-boot-dependencies。所以当你使用 Parent 时:

  • 不需要再引入 spring-boot-dependencies
  • Parent 已经通过继承获得了 BOM 的所有版本定义
  • Parent 在 BOM 之上额外添加了插件配置

本质区别:

  • spring-boot-starter-parent

    • 定位: 父工程 POM
    • 职责: 版本管理 + 默认配置 + 插件管理
    • 特征: 不包含任何代码 jar 包
    • 作用: 继承 spring-boot-dependencies 获得版本管理,再配置插件和构建默认值
  • spring-boot-starter

    • 定位: 核心启动器
    • 职责: 提供最基础的代码集合
    • 内容: Spring Core + AutoConfigure + Logging + YAML 解析
    • 适用: 非 Web 应用(定时任务、纯后台服务)
  • spring-boot-starter-web

    • 定位: Web 启动器
    • 内容: 包含 spring-boot-starter + Tomcat + Spring MVC + Jackson
    • 适用: API 接口、Web 应用

使用关系:

有了 Parent,必须引入至少一个 Starter
├─ Web 项目: 引入 spring-boot-starter-web (已包含 starter,无需再引)
└─ 非 Web 项目: 引入 spring-boot-starter

三、Maven 插件机制

3.1 插件标签结构

Maven 通过 <build><plugins> 配置构建行为:

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<!-- 插件配置参数 -->
</configuration>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
6 collapsed lines
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

核心标签含义:

  • <plugins>: 插件列表,真正引入并执行插件
  • <pluginManagement>: 插件管理,声明版本和配置,类似 dependencyManagement
  • <version>: 插件版本号
  • <configuration>: 插件参数配置
  • <executions>: 绑定插件目标到 Maven 生命周期阶段
  • <phase>: 生命周期阶段(validate/compile/test/package/install/deploy)
  • <goals>: 插件目标(如 compile/test/jar/repackage)

插件分类:

Build Plugins (构建插件)
├── 编译期: maven-compiler-plugin, maven-resources-plugin
├── 测试期: maven-surefire-plugin, maven-failsafe-plugin
├── 打包期: maven-jar-plugin, maven-war-plugin
└── 部署期: maven-deploy-plugin
Reporting Plugins (报告插件)
├── maven-javadoc-plugin
├── maven-checkstyle-plugin
└── maven-pmd-plugin

3.2 生命周期与插件绑定

Maven 构建生命周期:

clean 生命周期:
pre-clean → clean → post-clean
default 生命周期 (构建核心):
validate → compile → test → package → install → deploy
↑ ↑ ↑ ↑ ↑ ↑
| | | | | |
验证项目 编译 测试 打包 安装 部署
site 生命周期:
pre-site → site → post-site → site-deploy

默认插件绑定:

生命周期阶段绑定插件插件目标
compilemaven-compiler-plugincompile
testmaven-surefire-plugintest
packagemaven-jar-pluginjar
installmaven-install-plugininstall
deploymaven-deploy-plugindeploy

3.3 pluginManagement vs plugins

公式:

pluginManagement = 插件菜单(声明版本和配置)
plugins = 引入插件(真正执行)

区别:

  • <pluginManagement>

    • 声明插件版本和默认配置
    • 不执行插件
    • 通常在父 POM 中定义
  • <plugins>

    • 真正引入并执行插件
    • 可继承 pluginManagement 的配置

示例:

<!-- 父 POM: pluginManagement -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
12 collapsed lines
</build>
<!-- 子 POM: plugins -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- 无需写 version 和 configuration,继承父 POM -->
</plugin>
</plugins>
</build>

3.4 maven-compiler-plugin (编译插件)

作用:

  • .java 源文件编译成 .class 字节码
  • 绑定到 compile 阶段

核心参数:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<!-- 编译目标版本 -->
<source>17</source>
<target>17</target>
<!-- JDK 9+ 可用,替代 source/target -->
<release>17</release>
<!-- 编译编码 -->
<encoding>UTF-8</encoding>
7 collapsed lines
<!-- 编译器参数 -->
<compilerArgs>
<arg>-parameters</arg> <!-- 保留方法参数名(反射可用) -->
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>
</plugin>

使用场景:

  • 指定 Java 版本(如 Java 17)
  • 保留方法参数名(Spring MVC 等框架需要)
  • 自定义编译器选项

3.5 spring-boot-maven-plugin (Spring Boot 打包插件)

作用:

  • 将普通 JAR 重新打包成可执行 Fat JAR
  • 核心目标: repackage,绑定到 package 阶段

工作流程:

1. mvn package 执行
2. 生成普通 JAR (不含依赖)
3. repackage 目标执行
4. 原始 JAR 重命名为 xxx.original
5. 创建新的 Fat JAR:
- BOOT-INF/classes: 你的代码
- BOOT-INF/lib: 所有依赖 jar
- org.springframework.boot.loader: 启动加载器

Fat JAR 结构:

my-app.jar
├── META-INF/
│ └── MANIFEST.MF # 主类: org.springframework.boot.loader.JarLauncher
├── org/springframework/boot/loader/ # 类加载器
├── BOOT-INF/
│ ├── classes/ # 你的 .class 文件
│ └── lib/ # 依赖的第三方 jar
│ ├── spring-core.jar
│ ├── jackson-databind.jar
│ └── ...

配置示例:

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 指定主类(通常自动检测) -->
<mainClass>com.example.Application</mainClass>
<!-- 排除某些依赖 -->
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
15 collapsed lines
<!-- 可执行 jar 归档器配置 -->
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

使用场景:

  • 生成可直接运行 java -jar app.jar 的包
  • 微服务部署
  • 容器化部署(Docker)

3.6 两个插件对比

公式:

maven-compiler-plugin = 编译期 (.java → .class)
spring-boot-maven-plugin = 打包期 (.class → 可执行 .jar)

生命周期位置:

validate → compile → test → package → install → deploy
↑ ↑
maven-compiler-plugin spring-boot-maven-plugin
(编译源代码) (repackage 目标)
维度maven-compiler-pluginspring-boot-maven-plugin
阶段编译期打包期
输入.java 文件.class 文件 + 依赖 jar
输出.class 文件可执行 .jar
必需性必需(所有 Java 项目)Spring Boot 项目必需
独立性可单独使用依赖 compiler 的输出
产物大小小(仅代码)大(包含所有依赖)
默认绑定compile 阶段package 阶段(repackage 目标)

四、两种实践方案

4.1 方案一: 继承 Parent (推荐,最省事)

<!-- 获得版本管理和插件配置 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<dependencies>
<!-- 真正引入依赖,无需写版本号 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

4.2 方案二: 自定义父工程 (当不能继承 Spring Boot Parent 时)

⚠️ 缺失: 插件配置

BOM Import 只引入版本管理,不包含插件配置。必须手动配置:

<dependencyManagement>
<dependencies>
<!-- 引入版本字典,不引入 jar 包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 必须手动配置插件 -->
<build>
20 collapsed lines
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- 真正引入依赖,依然无需写版本号 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

方案对比:

特性Parent 继承BOM Import
依赖版本管理✅ 自动✅ 自动
插件版本管理✅ 自动❌ 需手动
Java 编译配置✅ 自动❌ 需手动
资源编码配置✅ 自动❌ 需手动
继承灵活性❌ 单继承✅ 可导入多个 BOM

五、核心结论

  1. Parent 提供双重管理 → 依赖版本 + 插件配置
  2. BOM 只管依赖版本 → 插件配置需手动补全
  3. dependencyManagement 只是菜单 → 不会导致项目臃肿,只有 dependencies 才真正引入
  4. Starter-Web 已包含 Starter → 无需重复引入
  5. BOM + Import 破解单继承 → 代价是失去插件配置,需手动补充
  6. Compiler 编译代码 → 生成 .class,是构建的第一步
  7. Spring Boot Plugin 打包部署 → 生成可执行 jar,是构建的最后一步

参考资料

Maven 基础机制

BOM 与依赖管理

Maven 插件

官方文档

本文标题:Spring Boot Maven 依赖与插件管理:从 Parent 到 BOM 的完整机制
文章作者:Zane
发布时间:2026-01-07