Apache Maven 作为 Java 生态中最重要的构建与依赖管理工具,自 Maven 3 发布至今已经十多年。表面上看,Maven 依然“能用”,但在大型工程、模块化体系、CI/CD 环境中,它的设计局限早已暴露无遗。
Maven 4 并不是一次激进的重写,而是一场针对构建模型本身的系统性重构。它解决的不是“语法是否更简洁”,而是长期困扰 Java 工程的结构性问题:构建语义混乱、模块扩展困难、生命周期僵化,以及对现代 Java 特性的支持不足。
一、为什么 Maven 4 必须重来一次
在 Maven 3 时代,一个 POM 文件同时承担了三种职责:
描述项目如何构建
描述项目对外暴露的依赖关系
描述多模块工程的结构
这种设计在小项目中问题不大,但在大型工程中会带来明显副作用:
发布到仓库的 POM 包含大量构建插件和内部 profile
依赖消费者需要解析与自身无关的信息
多模块工程维护成本随规模线性增长
与此同时,Java 生态本身也发生了变化:模块化(JPMS)、注解处理器、并行构建、可复现构建、供应链安全,都对构建工具提出了更高要求。
Maven 4 的核心目标只有一个:让 Maven 的“模型”重新变得清晰和可推理。
二、POM 模型升级:4.1.0 不只是一个版本号
Maven 4 引入了新的 POM 模型版本 4.1.0。这一变化看似简单,实则意义重大。
<project xmlns="http://maven.apache.org/POM/4.1.0">
<modelVersion>4.1.0</modelVersion>
</project>
4.1.0 的引入,为 Maven 后续一系列改进提供了语义空间,使 Maven 可以在保持向后兼容的前提下,引入更清晰的结构划分。
需要强调的是:
升级到 Maven 4 并不强制你立刻修改所有 POM,但只有在 4.1.0 模型下,Maven 才能完整表达新的构建与依赖语义。
三、构建 POM 与 Consumer POM 分离:真正解决“POM 臃肿”的问题
这是 Maven 4 最重要、也最具架构价值的改动之一。
在 Maven 3 中,发布到仓库的 POM 与本地构建使用的是同一份文件,这意味着:
插件配置会被传播
内部构建 profile 会被继承
消费者需要解析大量无关内容
Maven 4 明确区分了两类 POM:
Build POM:用于本地构建,包含完整构建逻辑
Consumer POM:发布到仓库,仅保留依赖与对外语义
在构建时,Maven 可以生成并发布一个精简后的 Consumer POM:
mvn install -Dmaven.consumer.pom.flatten=true
这一机制带来的价值非常直接:
仓库中的 POM 更小、更清晰
依赖解析更快
构建细节不再泄露
从工程视角看,这是 Maven 向“构建工具”和“依赖描述语言”职责分离迈出的关键一步。
四、Artifact 类型扩展:让依赖“说清楚自己是什么”
长期以来,Maven 对依赖的理解过于粗糙,一个 jar 到底意味着什么,完全依赖插件和编译器去猜。
Maven 4 引入了更细粒度的 artifact 类型,用类型本身表达语义,尤其是在模块化和注解处理器场景中。
例如,注解处理器可以被明确声明为 processor 类型:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<type>processor</type>
</dependency>
这种设计带来的好处是:
不再依赖插件私有约定
构建行为更加可预测
Java 模块化工程配置显著简化
从长期来看,这为 Maven 更好地适配 JPMS、AOT 编译、原生镜像等技术奠定了基础。
五、多模块工程的根本改进:Subprojects 与结构推断
如果你维护过大型 Maven 多模块项目,一定对 <modules> 的维护成本深有体会。
Maven 4 用 <subprojects> 重新定义了多模块工程的结构语义:
<subprojects>
<subproject>module-a</subproject>
<subproject>module-b</subproject>
</subprojects>
但变化并不止于此:
Maven 可以自动发现子项目
子项目的父关系和版本可以被推断
子模块增删不再需要反复修改父 POM
这使父 POM 更接近“工程逻辑根”,而不是配置堆积场所。
对于大型工程而言,这一改动显著降低了结构维护成本,也让 Maven 的“约定优于配置”第一次在多模块场景中真正成立。
六、生命周期模型重构:从线性执行到结构化调度
Maven 3 的生命周期本质是线性的,插件只能绑定到固定阶段,复杂构建往往需要“挤阶段”。
Maven 4 将生命周期视为一个有依赖关系的执行结构,而不是简单顺序列表:
模块之间形成执行依赖树
满足条件即可并行执行
生命周期更贴近真实构建过程
同时,引入了更清晰的 before / after 钩子语义:
<execution>
<phase>before:compile</phase>
</execution>
这使插件作者和构建工程师能够更精确地表达“在什么之前或之后执行”,而不再依赖隐含顺序。
七、配置模型的整体收紧:更严格,但更安全
Maven 4 在多个细节上体现了一个明确态度:宁可早失败,也不要静默出错。
典型变化包括:
默认情况下,启用不存在的 profile 会直接失败
构建参数和结构配置更明确
对非标准行为的容忍度降低
这些改动在短期内可能让部分项目“感觉更严格”,但在 CI/CD 和团队协作环境中,能显著降低隐性风险。
八、迁移 Maven 4 的现实建议
从工程实践角度看,升级 Maven 4 并不需要“一步到位”:
现有 Maven 3 项目通常可以直接在 Maven 4 下构建
新特性可以按需逐步启用
多模块和 Consumer POM 的收益在中大型项目中尤为明显
更重要的是,Maven 4 的设计方向非常明确:
它在为未来十年的 Java 构建体系做准备,而不是解决短期语法问题。
九、结语:Maven 4 的真正价值
Maven 4 并不是一次表层优化,而是一场针对构建模型、依赖语义和工程结构的系统性修复。
它解决的核心问题包括:
构建与依赖语义混杂
多模块工程维护成本过高
生命周期扩展能力不足
对现代 Java 特性的支持不自然
如果你维护的是中大型 Java 项目,Maven 4 不再是“要不要用”的问题,而是什么时候开始评估、如何逐步引入的问题。
从这个意义上说,Maven 4 是一次迟到的升级,但它来得正是时候。