面试追问地图
| 主问题 | 必讲关键点 | 下一层追问 |
|---|---|---|
| 生命周期 | clean/default/site、阶段顺序 | Phase 与 Goal 的绑定 |
| Scope | 编译、测试、运行、传递 | provided 在 Spring Boot jar 中的影响 |
| 依赖冲突 | 最近优先、先声明 | dependencyManagement、排除 |
| BOM | 统一兼容版本 | import scope、与 parent 的区别 |
| 多模块 | 聚合、继承、依赖方向 | 循环依赖如何治理 |
| Snapshot | 可变开发版本 | 仓库更新策略、为何生产禁用 |
| 可重复构建 | 固定版本、统一工具、同一制品 | 时间戳、环境差异 |
| 供应链安全 | 漏洞扫描、SBOM、仓库治理 | 依赖混淆、传递依赖漏洞 |
| 构建优化 | 缓存、增量、并行、测试分层 | 如何保证优化后结果一致 |
构建题要能根据 dependency:tree 解释一个真实冲突,而不是只背 Maven 命令。
一、Maven 基础
Maven 的生命周期有哪些?
难度 🟡
Maven 主要有三套生命周期:
- clean:清理构建输出。
- default:编译、测试、打包、验证、安装、部署。
- site:生成项目站点。
常见阶段:
validate → compile → test → package
→ verify → install → deploy执行后面的阶段会依次执行前面的阶段。
生命周期、Phase、Goal、Plugin 的关系?
- Lifecycle:构建过程。
- Phase:生命周期中的阶段。
- Plugin:提供具体构建能力。
- Goal:插件中的具体任务。
Phase 本身不执行代码,它绑定一个或多个 Plugin Goal。
package、install、deploy 的区别?
package:生成 jar/war。install:将制品安装到本地仓库。deploy:上传到远程仓库供团队使用。
二、依赖解析
Maven 依赖范围有哪些?
| Scope | 编译 | 测试 | 运行 | 是否传递 |
|---|---|---|---|---|
| compile | 是 | 是 | 是 | 是 |
| provided | 是 | 是 | 否 | 否 |
| runtime | 否 | 是 | 是 | 是 |
| test | 否 | 是 | 否 | 否 |
| system | 是 | 是 | 否 | 否 |
system 依赖可移植性差,通常不推荐。
Maven 如何解决依赖冲突?
难度 🔴
默认采用:
- 路径最近优先。
- 路径相同时,先声明优先。
治理方式:
dependencyManagement统一版本。- BOM 管理一组兼容依赖。
exclusions排除错误传递依赖。mvn dependency:tree查看来源。
不能只靠调整声明顺序解决长期依赖治理问题。
dependencies 和 dependencyManagement 的区别?
dependencies:真正引入依赖。dependencyManagement:只声明默认版本和范围,子模块使用时仍需显式引入。
父 POM 常用 dependencyManagement 统一版本。
BOM 是什么?
BOM 是只用于管理依赖版本的 POM,可通过 scope=import 导入。
它能确保同一技术栈的一组依赖使用兼容版本,例如 Spring Boot Dependencies。
三、多模块与继承
Maven 聚合和继承有什么区别?
- 聚合:父工程通过
<modules>一次构建多个模块。 - 继承:子 POM 继承父 POM 的配置。
两者经常同时使用,但不是同一概念。
多模块项目如何划分?
按稳定职责和依赖方向划分,例如:
api → application → domain → infrastructure避免模块循环依赖,也不要为了形式把每个包都拆成模块。
Snapshot 和 Release 的区别?
- Snapshot 可在同一版本号下更新,适合开发迭代。
- Release 应不可变,不允许覆盖。
生产发布应使用可追溯的 Release 版本和制品摘要。
四、构建可重复性
什么是可重复构建?
相同源码、依赖和配置应生成行为一致、可验证的制品。
需要:
- 固定插件和依赖版本。
- 使用受控仓库。
- 避免动态版本和本机路径。
- 记录 JDK、构建工具和环境。
- 制品一次构建,多环境晋级。
为什么不能在不同环境重新构建?
重新构建可能引入:
- 依赖版本变化。
- 插件或 JDK 差异。
- 环境变量差异。
测试环境验证过的应是最终进入生产的同一份制品。
Maven Wrapper 有什么作用?
Wrapper 将 Maven 版本配置纳入项目,开发和 CI 可使用统一版本执行构建,减少环境差异。
五、依赖安全
如何治理依赖漏洞?
- 定期执行依赖漏洞扫描。
- 区分直接依赖和传递依赖来源。
- 优先升级到官方修复版本。
- 无法升级时评估是否实际使用漏洞路径,并采取隔离措施。
- 保留 SBOM 和升级记录。
什么是依赖混淆攻击?
当构建工具从公共仓库解析到与内部包同名但版本更高的恶意依赖时,可能错误下载恶意包。
防护:
- 内部包使用明确命名空间。
- 配置受控镜像和仓库优先级。
- 禁止随意访问未知仓库。
- 校验制品签名和哈希。
为什么不应该使用不受控的动态版本?
动态版本会导致同一提交在不同时间解析出不同依赖,破坏可重复构建,也增加供应链风险。
六、CI 构建优化
Maven 构建慢怎么优化?
- 分析耗时阶段和插件。
- 使用本地/远程依赖缓存。
- 只构建受影响模块。
- 合理并行构建。
- 区分快速单元测试和较慢集成测试。
- 避免每次重新下载依赖和 Docker 基础层。
是否应该跳过测试加快构建?
开发阶段可按需要跳过特定测试,但合并和发布流水线不应默认跳过关键测试。
应通过测试分层、并行和缓存提升速度,而不是长期关闭质量门禁。