跳到主要内容
约 5 分钟3 张卡

Maven

Maven 用生命周期、插件和依赖图组织构建。本文以 Maven 3 为范围,讲解阶段执行与依赖收敛。

1. 面试核心​

先记住这几条,再读正文
  • 生命周期与插件。 phase 定义执行阶段,绑定的插件 goal 执行具体工作。
  • 依赖仲裁。 未受显式管理时,依赖仲裁采用最近路径,同深度先声明者优先。卡 · 生命周期
  • 版本管理与引入。 dependencyManagement 管理版本,直接或传递依赖负责实际引入。
  • 集成测试。 mvn verify 会执行集成测试及其后的 post-integration-test 清理阶段,再由 Failsafe 检查测试结果。卡 · 集成测试阶段
  • 多模块构建。 mvn -pl app -am verify 构建 app 及其 reactor 依赖。卡 · 聚合、继承与 reactor

2. 生命周期​

clean、default 与 site 是独立生命周期。default 的常用阶段如下:

validate → compile → test → package → verify → install → deploy

执行一个 phase 时,会先执行同生命周期的前置阶段。mvn clean verify 先清理,再执行 default 到 verify。

install 把产物安装到本地仓库。deploy 发布到远程仓库,供其他项目使用。应用上线由 CD 完成。

3. 插件 goal​

phase 是阶段,goal 是插件提供的具体动作。packaging 和项目配置决定哪些 goal 绑定到阶段。

Surefire 执行单元测试,Failsafe 用于集成测试。集成测试需显式配置相应 goal。仅执行某个 phase,并不会自动补齐缺少的插件绑定。

插件版本与 JDK 版本一同固定。重复绑定需检查父 POM 与子模块的有效配置。

4. Scope​

scope类路径与传递
compile默认范围,进入主编译、测试与运行,可传递
provided主编译与测试可用,运行环境提供,不传递
runtime测试与运行可用,主编译不可用
test仅测试使用,不向下游传递

传递依赖的最终 scope 取决于两段路径的 scope。system 指向本地文件,降低跨环境可移植性。import 用于 dependencyManagement 中导入 POM。

5. 依赖仲裁​

未显式管理的冲突按最近路径选版本。同深度时,先声明的路径优先。显式依赖与 dependencyManagement 可控制实际选择。

mvn dependency:tree
mvn help:effective-pom

依赖树显示引入路径,有效 POM 显示继承后的配置。修复可采用升级上游、精确 exclusion 或显式版本。版本统一后仍需验证二进制兼容性。

6. dependencyManagement 与 BOM​

dependencyManagement 提供依赖版本与默认配置。单独列在这里的坐标不会进入类路径。直接声明或传递依赖遇到它时,管理规则才参与解析。

BOM 以 type=pom、scope=import 导入管理项。导入 BOM 本身只带入这些版本规则。

pluginManagement 提供插件版本与配置。插件由生命周期或显式声明使用后,相关配置才生效。项目的 dependencyManagement 不管理插件自身依赖。

7. 依赖收敛检查​

Enforcer 的 dependencyConvergence 检查依赖路径版本一致性。它与只看仲裁后的最终 jar 集合不同。

可通过 dependencyManagement 或精确排除消除分叉。例外应写明坐标、原因和期限。重复类检查需要额外规则,并非收敛规则的职责。

8. 可重复构建​

固定 JDK、Maven、依赖、插件与仓库输入。Maven Wrapper 固定 Maven 分发版本。Toolchains 声明构建所需工具链。

project.build.outputTimestamp 可稳定归档时间戳。字符集、时区和代码生成工具也需固定。

独立重建后比较产物摘要,才能验证字节级重复性。部署使用同一产物的方式见可重复交付。

9. 聚合、继承与 reactor​

聚合通过 modules 收集构建模块。继承通过 parent 复用配置。聚合 POM 与父 POM 可以是同一个,也可以分开。

Reactor 根据实际依赖关系排序模块。仅列在 dependencyManagement 中的依赖不影响排序。

mvn -pl app -am verify

该命令选择 app,并构建它依赖的 reactor 模块。-amd 则选择依赖当前所选模块的下游模块。执行前需位于包含这些模块的聚合工程。

10. 集成测试阶段​

配置 Failsafe 的 integration-test 与 verify goal 后,使用 mvn verify。

Failsafe 在 integration-test 阶段记录测试失败。随后 post-integration-test 阶段仍可清理测试环境。verify 阶段检查结果,并决定构建是否失败。

只运行 mvn integration-test 会跳过后续阶段。测试清理与最终结果检查因此缺失。

11. 常见问题​

11.1 package 与 install​

package 生成 jar 或 war。install 还将产物与 POM 写入本地仓库。Reactor 可在同次构建中使用其他模块产物。

11.2 NoSuchMethodError 与类路径​

12 · 面试题卡片​

12.1 Maven 如何选择冲突依赖,怎样让多模块版本收敛​

出现公司:阿里巴巴、字节跳动、华为

考察重点

  • 理解生命周期 phase 与插件 goal。
  • 理解最近定义、dependency tree 和 scope。
  • 理解dependencyManagement、BOM 与 convergence。

相关内容:生命周期至可重复构建。

参考回答

Maven 对未受显式管理的冲突采用最近路径规则。

同深度时,先声明者优先。用 dependency:tree 确定引入路径,再决定升级或管理版本。

父 POM 或 BOM 用 dependencyManagement 统一规则。依赖仍由直接声明或传递路径引入。Enforcer 的 dependencyConvergence 检查版本分叉。CI 同时固定工具链、插件和归档时间,并执行兼容性测试。

12.2 Maven 的聚合和继承有什么区别,怎样构建一个模块及其依赖?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:modules、parent 与 reactor 排序。

相关内容:聚合、继承与 reactor。

参考回答

聚合决定一起构建哪些模块,继承决定复用哪些配置。

Maven 3 中可执行 mvn -pl app -am verify。它选择 app,并构建 app 依赖的 reactor 模块。实际依赖参与排序,管理项本身不参与排序。

12.3 Failsafe 集成测试为什么应执行 verify?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:测试失败、环境清理与结果检查。

相关内容:集成测试阶段。

参考回答

verify 会覆盖集成测试、后续清理和最终结果检查。

Failsafe 将测试失败留到 verify 阶段报告。post-integration-test 因此能先清理环境。仅执行 integration-test 会跳过这些后续阶段。

13. 参考资料​