Maven 4 深度拆解:15年后,Java 构建工具的「彻底重构」——从 POM 4.1.0 模型分离到依赖解析器 2.0 的工程全貌(2026)
前言
2026年7月,Apache Maven 4 的正式 GA 版本终于要来了。
从 2010 年 Maven 3.0 发布到今天,已经过去了整整 16 年。这 16 年里,Java 生态经历了 Spring Boot 的崛起、微服务的爆发、容器化的浪潮,云原生成为标配,GraalVM Native Image 让 Java 应用可以编译成原生二进制——而 Maven 本身,几乎一直停在 3.x 版本的舒适区里小幅迭代。
不是 Maven 团队不努力,而是 POM(Project Object Model)这个核心模型背负了太多历史包袱:它既是开发者的"构建脚本",又是发布到 Maven Central 的"依赖清单",还是 IDE、Gradle、以及无数插件的"契约文档"。要动 POM 格式,意味着整个生态链都要跟着改。
Maven 4 的解题思路非常优雅:把"构建用的 POM"和"给别人用的 POM"分开。这一刀切下去,整个架构就理顺了。本文从工程师视角,深度拆解 Maven 4 的核心变化、架构设计、新工具链,以及从 Maven 3 的完整迁移路径。
一、背景:为什么 POM 格式被「冻住」了 16 年
1.1 Maven 的历史包袱
理解 Maven 4 的设计,需要先理解 Maven 3 的局限。
2004 年,Maven 2 以 POM(Project Object Model)为核心,统一了 Java 项目的构建标准。pom.xml 集"依赖管理"、"构建配置"、"项目元信息"于一身,这种 All-in-One 的设计在彼时极大提升了开发效率。
但问题也随之而来。
POM 背负了四种职责,却只有一个身份:
- 开发构建配置:团队内部用 POM 配置插件、profile、properties
- 依赖声明契约:发布到 Maven Central 后,下游通过 POM 了解依赖信息
- IDE 集成协议:IntelliJ IDEA、Eclipse 通过 POM 理解项目结构
- Gradle 互操作层:Gradle 也需要解析 Maven POM 来消费依赖
当一个字段在 POM 里被修改时,以上所有四个角色都要重新理解。这意味着 POM 语法的任何改动都是"破坏性变更",必须协调整个生态。
2010 年 Maven 3 发布时,POM 版本定格在 4.0.0。之后的 16 年,这个版本号几乎没有变过——不是因为没需求,而是因为改了 POM 格式代价太大。
1.2 Maven 3 时代的三大痛点
痛点一:父 POM 版本必须显式声明
在 Maven 3 的多模块项目中,子模块每次都要写清楚父 POM 版本:
<!-- Maven 3:每个子模块都要写 version -->
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version> <!-- 这个版本号必须手动维护 -->
</parent>
<artifactId>child-service</artifact>
<version>1.0.0</version>
</project>
当父 POM 版本升级时,所有子模块都要逐一修改。CI 流水线上跑着几十个微服务,这种"改一处、动全身"的场景是真实噩梦。
痛点二:多源码目录依赖 Build Helper 插件
Java 项目想同时包含 Kotlin 和 Java 代码?在 Maven 3 时代,需要引入 build-helper-maven-plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>add-source</id>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/src/main/kotlin</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
这只是多源码目录一个功能,还有版本管理、IDE 集成等一系列配置需要额外插件。这种"基础能力靠插件凑"的设计,让 POM 文件越来越臃肿。
痛点三:${revision} 变量与 Flatten 插件的无奈
Maven 3 中想用 CI 友好的动态版本号(如 ${revision}),必须配合 flatten-maven-plugin:
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>${revision}</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendlies</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<goals>
<goal>flatten:clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
这还没完:flatten 插件本身又引入了新的生命周期和配置复杂度——mvn install 和 mvn deploy 的行为不一致,IDE 偶尔识别不了 flatten 后的 POM,各种边缘 case 让团队焦头烂额。
二、核心架构:Build POM 与 Consumer POM 分离
2.1 为什么需要分离
Maven 4 最大的架构改进,就是将 POM 的两种用途彻底分离:
- Build POM(构建 POM):存在于 Git 仓库中,是开发者的"源代码"。包含完整的插件配置、父 POM 引用、属性定义、profile 条件等构建信息。
- Consumer POM(消费 POM):发布到 Maven Central 的精简版,仅包含下游消费者真正需要的信息——依赖列表、依赖版本、传递依赖范围等。
这种分离的意义在于:构建系统可以大胆进化,而下游消费者完全无感。
2.2 自动生成 Consumer POM
Maven 4 在 mvn deploy 时自动完成这个转换。以下是转换逻辑的可视化理解:
Build POM (Git 仓库中的原始 pom.xml)
├── <parent> 引用(parent POM 全文内联)
├── <build> 完整插件配置(完全丢弃)
├── <properties> 内部属性(已求值后内联)
├── <profiles> 条件配置(保留生效的,丢弃未激活的)
└── <dependencies> 完整依赖声明
└── 传递依赖(仅保留实际使用的 scope)
↓ Maven 4 转换逻辑
Consumer POM (发布到 Maven Central)
├── <parent> 引用(已消除)
├── <properties> 仅保留消费相关的属性
├── <dependencies> 仅包含直接依赖(传递依赖展平)
└── 不包含任何 <build> 配置
这一转换由 Maven 4 内置完成,不需要任何插件。
2.3 如何开启 Consumer POM 扁平化
截至 RC-5 版本,Consumer POM 扁平化默认关闭,需要显式开启。有两种方式:
方式一:创建 .mvn/maven-user.properties
mkdir -p .mvn
# .mvn/maven-user.properties
maven.consumer.pom.flatten=true
方式二:命令行传递参数
mvn deploy -Dmaven.consumer.pom.flatten=true
方式三:在 .mvn/maven.config 中配置(推荐)
# .mvn/maven.config
-Dmaven.consumer.pom.flatten=true
.mvn/maven.config 是 Maven 4 引入的项目级配置机制,类似于 .mvn/extensions,可以在项目根目录存放,不影响源代码(通常加入 .gitignore),但对所有团队成员生效。
三、POM 4.1.0:少写 40% 配置的工程实践
3.1 父 POM 版本自动推断
这是 2005 年就提出的老需求,Maven 4 终于实现了。
Maven 3 的写法:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<version>1.2.0</version> <!-- 必须显式写版本 -->
</parent>
<artifactId>my-service</artifactId>
<version>1.2.0</version>
</project>
Maven 4 POM 4.1.0 的写法:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.1.0
https://maven.apache.org/xsd/maven-4.1.0.xsd">
<modelVersion>4.1.0</modelVersion>
<!-- 不写 version,Maven 自动从父目录推断 -->
<parent>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<!-- <version> 省略,Maven 自动继承父 POM 版本 -->
</parent>
<artifactId>my-service</artifactId>
<dependencies>
<!-- 同仓库子模块依赖也可省略 version -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common</artifactId>
<!-- 省略 version,Maven 识别为同仓库模块,自动推断 -->
</dependency>
</dependencies>
</project>
推断规则:
- 子模块
<version>省略时,自动继承父 POM 版本 - 依赖的模块如果存在于同一 Git 仓库(同一 reactor 构建中),
<version>可省略 - Maven 4 会自动处理 Reactor 依赖顺序,无需手动指定
3.2 子模块自动发现
Maven 3 的多模块项目必须在父 POM 中显式列出所有子模块:
<!-- Maven 3:必须显式声明 -->
<modules>
<module>my-common</module>
<module>my-service</module>
<module>my-web</module>
</modules>
Maven 4 POM 4.1.0 实现了子模块自动发现——只要父 POM 使用 pom 打包且未手动声明 <subprojects>,Maven 4 会自动扫描当前目录下的所有子目录,发现 pom.xml 就纳入构建:
<!-- Maven 4 POM 4.1.0:自动发现 -->
<project xmlns="http://maven.apache.org/POM/4.1.0">
<modelVersion>4.1.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 不写 <modules>,子目录有 pom.xml 就会自动加入 -->
<!-- 如果需要手动控制,加上 <subprojects> 覆盖自动发现 -->
</project>
工程价值: 大型微服务仓库中,每次新增服务模块都不需要修改父 POM,减少了代码合并冲突(merge conflict)的频率。
3.3 CI 友好的版本号,不再需要 Flatten 插件
${revision} 在 Maven 3 中需要 Flatten 插件来"修正"发布后的 POM。在 Maven 4 中,这已经成为一等公民(first-class)支持:
<!-- Maven 4:内置支持 CI 版本号 -->
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>${revision}</version>
在 CI 流水线中指定版本:
# GitHub Actions / GitLab CI / Jenkins 均可
mvn verify -Drevision=1.2.0
mvn deploy -Drevision=1.2.0
在 .mvn/maven.config 中固定版本(开发时):
-Drevision=1.0.0-SNAPSHOT
mvn deploy 时,Maven 4 自动将 ${revision} 替换为实际值并写入 Consumer POM,不需要任何额外插件。
3.4 新的 BOM 打包类型
BOM(Bill of Materials)在 Maven 3 中使用 pom 打包,这与父 POM 的打包类型冲突,概念上不够清晰:
<!-- Maven 3 的 BOM:pom 打包与父 POM 无区别 -->
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Maven 4 POM 4.1.0 引入了专属的 bom 打包类型:
<!-- Maven 4:专属 BOM 打包类型 -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.1.0">
<modelVersion>4.1.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app-bom</artifactId>
<version>1.0.0</version>
<!-- 明确的 BOM 语义,职责单一 -->
<packaging>bom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
3.5 多源码目录,告别 Build Helper 插件
Maven 4 内置了多源码目录支持,不再需要 build-helper-maven-plugin:
<project xmlns="http://maven.apache.org/POM/4.1.0">
<modelVersion>4.1.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-kotlin-java-app</artifactId>
<build>
<sources>
<!-- 主 Java 源码 -->
<source>
<scope>main</scope>
<directory>src/main/java</directory>
</source>
<!-- Kotlin 源码 -->
<source>
<scope>main</scope>
<directory>src/main/kotlin</directory>
</source>
<!-- 测试代码 -->
<source>
<scope>test</scope>
<directory>src/test/java</directory>
</source>
<source>
<scope>test</scope>
<directory>src/test/kotlin</directory>
</source>
</sources>
</build>
</project>
同样内置的还有 <resources> 的多目录支持,以及更灵活的 <testOutputDirectory> 配置。
四、依赖解析器 2.0:从 Resolver 1.x 到 2.0
4.1 Maven Resolver 架构回顾
Maven 的依赖解析由独立组件 Maven Resolver(原名 Maven Artifact Resolver)负责。这是一个被 Maven、Maven Invoker、Maven Wrapper 等多个工具共享的库。
Maven 3 使用 Resolver 1.x,依赖解析的核心机制包括:
- Artifact 描述:groupId + artifactId + version + packaging + classifier
- Remote Repository 链:镜像 → 优先仓库 → 备选仓库
- 传递依赖解析:
<scope>控制(compile / provided / runtime / test / system) - 版本范围解析:
(1.0,2.0)语法
4.2 Resolver 2.0 的核心改进
Maven 4 内置 Resolver 2.0,带来了以下改进:
1. 更快的依赖解析
Resolver 2.0 重写了版本排序和冲突检测算法,在大型多模块项目中,依赖解析时间可减少 30-50%。这对于 CI 流水线意义重大——每次 mvn dependency:tree 和 mvn dependency:resolve 都更快。
2. 改进的快照(SNAPSHOT)处理
Maven 3 中,每次构建都会重新检查远程仓库中的 SNAPSHOT 版本(除非明确使用 -o 离线模式)。Resolver 2.0 提供了更精细的缓存策略:
<!-- settings.xml 中的新配置 -->
<profile>
<id>snapshot-update</id>
<properties>
<maven.snapshot.updatePolicy>daily</maven.snapshot.updatePolicy>
</properties>
</profile>
3. 改进的 POM 验证
Resolver 2.0 在解析 Consumer POM 时会进行更严格的 Schema 验证,减少因 POM 文件不完整或格式错误导致的构建失败。
4. Provider 机制增强
Resolver 2.0 引入了更灵活的**协议处理器(Protocol Provider)**扩展机制,允许第三方实现自定义的仓库协议(如 s3:、gcs: 等),而不需要依赖特定的 Wagon 实现。
4.3 与 Gradle 的互操作性提升
Consumer POM 的标准化实际上也改善了 Maven 与 Gradle 的互操作:
- Gradle 在解析 Maven 依赖时,Consumer POM 只传递真正需要的依赖(直接依赖),避免将父 POM 中的插件配置误解析为传递依赖
- 构建 POM 的插件配置不会泄露到下游,减少了 Gradle 项目引用 Maven 模块时的歧义
五、新工具链:从手动迁移到智能升级
5.1 Maven Upgrade Tool(mvnup)
Maven 4 官方推出了升级助手工具 mvnup,提供两步走迁移:检查 + 自动修复。
安装:
# 通过 Maven Wrapper 或直接安装
mvn wrapper:wrapper -Dmaven=4.0.0
第一步:检查兼容性
mvnup check
输出示例:
[INFO] Scanning project: my-app
[INFO] Checking Maven 4 compatibility...
[WARNING] POM model version is 4.0.0 - consider upgrading to 4.1.0
[WARNING] build-helper-maven-plugin detected - see https://maven.apache.org/docs/maven-4/upgrading.html#build-helper
[WARNING] flatten-maven-plugin detected - see https://maven.apache.org/docs/maven-4/upgrading.html#flatten
[ERROR] Project requires Java 8 - Maven 4 requires Java 17+ to run Maven itself
第二步:应用修复
mvnup apply
mvnup 会根据检测结果自动修改 POM 文件,例如将 Flatten 插件替换为 Maven 4 内置的版本管理,将 Build Helper 插件的配置迁移为原生配置。
5.2 Maven Shell(mvnsh)
Maven Shell 是一个交互式 REPL,类似 Python 的 python 或 Node.js 的 node:
mvnsh
__ ____ __
\ \ / / \ \ / / \
\ \ /\ / / \ \ === / / / /
\ \/ \/ / \ \ / / / /
\___/\/ / \_\ /_/ / /
Maven Shell 4.0.0
mvn> compile
[INFO] Compiling 142 source files...
[INFO] BUILD SUCCESS
mvn> test -pl my-service
[INFO] Running MyServiceTest...
[INFO] Tests run: 42, Failures: 0, Errors: 0
mvn> exit
适用场景:
- 多模块项目开发时,不需要每次都敲完整的
mvn命令 - 快速测试不同插件配置
- 交互式调试构建问题
5.3 智能续跑(Resume Build)
这是 Maven 4 中我认为最实用的功能之一。
在 Maven 3 的多模块项目中,如果 module-C 构建失败,修复后需要重新跑整个构建(mvn install)或者记住从哪个模块开始(mvn install -pl module-C,module-D)。
Maven 4 的 -r(--resume)参数让这个流程自动化:
# 首次构建,遇到 module-C 失败
mvn verify
[INFO] Building module-A [SUCCESS]
[INFO] Building module-B [SUCCESS]
[INFO] Building module-C [FAILURE] ← 失败,退出
# 修复代码后,从失败处继续
mvn verify -r
[INFO] Resuming from module-C (previous build state preserved)
[INFO] Building module-C [SUCCESS]
[INFO] Building module-D [SUCCESS]
[INFO] Building module-E [SUCCESS]
Maven 4 在 .mvn/resume.properties 中保存了构建状态(哪些模块成功、哪个模块失败),-r 读取这个状态并智能续跑。
--resume-from 精确续跑:
# 从指定模块开始续跑(覆盖上次失败点)
mvn verify -r -rf :module-D
5.4 日志输出优化
Maven 4 改进了构建日志的输出格式:
- 彩色输出:不同日志级别用不同颜色显示(INFO 绿、WARN 黄、ERROR 红)
- 进度条:在下载依赖、编译等长时间操作时显示进度
- 并行构建更清晰:多模块并行构建时,输出不再交错混乱
六、运行要求与 Java 版本
6.1 Java 版本要求
这是最重要的breaking change:
| 维度 | Maven 3.x | Maven 4 |
|---|---|---|
| 运行 Maven 本身 | Java 8+ | Java 17+ |
| 编译项目代码 | 自行配置 | 自行配置(仍可编译 Java 8/11/17) |
| POM 模型版本 | 4.0.0 | 4.0.0 构建 / 4.1.0 新语法 |
| 依赖解析器 | Resolver 1.x | Resolver 2.0 |
关键澄清:Maven 4 要求 Java 17+ 指的是运行 Maven 本身,而不是你的项目代码。借助 Maven Toolchains,你仍然可以编译 Java 8/11/17 的项目代码:
<!-- 父 POM 配置 Toolchains -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<!-- 指向 JDK 8 安装路径 -->
<jdkToolchain>
<version>8</version>
</jdkToolchain>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
6.2 Java 17 的实际意义
要求 Java 17 对团队来说其实是个好消息:
- Maven 本身使用 Java 17 的新特性(Records、Sealed Classes、Pattern Matching 等),代码更简洁、安全性更好
- 现代 JDK 的 JIT 编译器对 Maven 这种大量 IO + 反射操作的应用有显著性能提升
- GC 改进(ZGC、Shenandoah)降低了长时间 CI 构建的停顿
七、从 Maven 3 迁移:四步实战路径
7.1 迁移决策树
你的项目是什么情况?
│
├─ 纯内部项目,不对外发布依赖
│ └─ Maven 4 完全可选,收益有限
│
├─ 发布的库/框架(发布到 Maven Central / 私有仓库)
│ └─ 必须迁移,Consumer POM 改进是关键收益
│
├─ 多模块项目(10+ 子模块)
│ └─ 推荐迁移,子模块自动发现 + 智能续跑大幅提升效率
│
└─ 使用了 Flatten 插件或 build-helper 插件
└─ 强烈推荐迁移,消除插件依赖
7.2 稳妥迁移四步法
第一步:环境准备
# 安装 Java 17+
java -version
# openjdk version "17.0.12" 2026-07-17
# 安装 Maven 4 RC
wget https://dlcdn.apache.org/maven/maven-4/4.0.0-rc-5/binaries/apache-maven-4.0.0-rc-5-bin.tar.gz
tar xzf apache-maven-4.0.0-rc-5-bin.tar.gz
export PATH=$HOME/apache-maven-4.0.0-rc-5/bin:$PATH
# 验证
mvn -version
# Apache Maven 4.0.0-rc-5
第二步:运行兼容性检查
mvnup check
根据输出,逐一处理 WARNING 和 ERROR。
第三步:升级 POM 模型版本(可选但推荐)
<!-- pom.xml -->
<modelVersion>4.0.0</modelVersion>
<!-- 改为 -->
<modelVersion>4.1.0</modelVersion>
然后应用 POM 4.1.0 的新特性(父版本自动推断、子模块自动发现等)。
第四步:测试构建
# 先在本地测试
mvn clean verify
# 多模块项目测试续跑
mvn clean install # 第一次全量构建
# 修改某个子模块的代码
mvn clean install -r # 从失败点续跑
# 测试 Consumer POM 生成
mvn deploy -Dmaven.consumer.pom.flatten=true
# 验证生成的 pom.xml(在 target 目录)
cat target/.flattened-pom.xml
八、Gradle vs Maven 4:2026 年的构建工具选型
8.1 Gradle 的优势
必须承认,在某些维度 Gradle 依然领先:
- Kotlin DSL / Groovy DSL:比 XML 的声明式配置更强大、更类型安全
- 增量构建:Gradle 的增量构建引擎比 Maven 的
@RequiresDependencyCollection更智能 - Build Cache:Gradle Remote Build Cache 在多 CI 节点场景下效果更好
- Configuration Cache:提前配置解析,减少大型项目的初始化时间
8.2 Maven 4 追上来了什么
Maven 4 的改进直接对标 Gradle 的优势:
| 能力 | Maven 3 | Maven 4 | Gradle |
|---|---|---|---|
| 多源码目录 | 需要插件 | 内置 | 内置 |
| CI 版本号 | 需要 Flatten 插件 | 内置 | 内置 |
| 子模块自动发现 | 需要手动配置 | 内置 | 需要 settings.gradle |
| 智能续跑 | 不支持 | 内置 | 需要 --continue |
| 运行要求 | Java 8 | Java 17 | Java 8/11/17 |
| 依赖解析器版本 | Resolver 1.x | Resolver 2.0 | Gradle 内置 |
8.3 选型建议
选 Maven 4 的理由:
- 团队已经重度使用 Maven,迁移成本高
- 对 Maven Central 生态有强依赖(Spring、Hibernate、Apache 全家桶)
- 法规要求构建工具必须使用 Apache License 的开源项目
- 多模块企业项目,稳定性优先于灵活性
选 Gradle 的理由:
- 全新项目,可以从头设计构建逻辑
- 需要深度定制构建逻辑(自定义 Task 复杂度高)
- Kotlin DSL 是团队首选配置语言
- Android 项目(Gradle 是 Android 官方构建工具)
两者共存:
- 实际上很多大型项目同时使用 Maven 和 Gradle:Java 库用 Maven 构建并发布,Groovy/Kotlin 微服务用 Gradle
- Gradle 可以消费 Maven POM,Maven 4 的 Consumer POM 改进让这种互操作更顺畅
九、展望:Maven 的未来
9.1 Maven 4 之后
Maven 社区已经在讨论后续版本的方向:
- Maven 4.1+:可能引入更强大的 BOM 层级管理、依赖分组(Dependency Grouping)
- Maven 5 的构思:完全抛弃 XML POM,改为 YAML 或 TOML 格式(概念讨论阶段,远未立项)
- Bazel/Blaze 互操作:企业级 Java 项目逐渐引入 Bazel 做增量构建,Maven 可能在 Gradle 之外提供 Bazel 兼容层
9.2 Maven 在云原生时代的定位
Maven 4 的 Consumer POM 改进,恰好契合了云原生时代的软件供应链安全需求:
- Consumer POM 只暴露直接依赖,隐藏内部模块关系,减少了信息泄露
- 传递依赖的显式展平,让
dependency:tree的输出更可预测,利于安全扫描 - BOM 的
bom打包类型,让 Bill of Materials 的版本管理更规范
十、总结
Maven 4 不是一次版本号跳跃,而是一次架构级别的重构。它的核心价值可以归结为三点:
1. 分离了关注点:Build POM 交给开发者,Consumer POM 交给生态,两者各司其职,互不干扰。
2. 消除了历史包袱:POM 4.1.0 的新特性(父版本自动推断、子模块自动发现、内置 CI 版本号、多源码目录)让 POM 文件减少了 30-50% 的模板代码,开发者终于不用再为"构建工具的配置"浪费大量时间。
3. 提升了开发体验:mvnup 升级助手、mvnsh 交互式 Shell、智能续跑 -r、日志优化——这些看似小的改进,加起来极大提升了日常开发效率。
对于已经在用 Maven 3 的团队,建议在 Maven 4 GA 正式发布后,在测试环境验证兼容性问题,然后逐步迁移。对于新项目,直接用 Maven 4 POM 4.1.0 是合理的选择。
Java 构建工具经历了 15 年的等待,终于迎来了一次有深度的进化。这不只是版本号的更迭,更是 Maven 对现代软件开发需求的正式回应。
参考资料
- Apache Maven 4 Official Documentation: https://maven.apache.org/docs/maven-4/
- Maven 4 Upgrade Guide: https://maven.apache.org/docs/maven-4/upgrading.html
- Maven 4.0.0-rc-5 Release Notes: https://maven.apache.org/docs/4.0.0-rc-5/release-notes.html
- Maven Resolver 2.0: https://maven.apache.org/resolver/
- Maven Upgrade Tool (mvnup): https://github.com/apache/maven-upgrade