enforcedPlatform是硬性锁定,强制所有依赖(含传递依赖)服从BOM版本;platform是建议性对齐,显式声明的版本可覆盖BOM。

platform 和 enforcedPlatform 都是用来统一依赖版本的,但裁决时机和强制力完全不同
简单说:platform 是“建议性对齐”,Gradle 会尽量按它选版本,但遇到显式声明的直接依赖时可能被覆盖;enforcedPlatform 是“硬性锁定”,所有传递依赖都必须服从,连你手动写的 implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.0' 都会被降级或升级到 BOM 指定的版本。
什么时候该用 platform
适合多模块项目中想提供一套推荐版本,又不希望破坏下游模块的自主选择权。
- 你发布了一个内部 BOM(比如
com.example:bom:1.2.0),希望团队在新建子模块时默认拉取其中定义的 Jackson、OkHttp 等版本 - 某个子模块明确写了
implementation 'com.squareup.okhttp3:okhttp:4.11.0',那它就用 4.11.0,不会被platform覆盖 - 如果子模块只写
implementation 'com.squareup.okhttp3:okhttp'(不带 version),才会由platform补全为 BOM 中的版本 - 适用于协作宽松、演进渐进的中大型工程,比如微服务各团队保持一定自由度
什么时候必须用 enforcedPlatform
当你需要彻底杜绝运行时 NoSuchMethodError 或 ClassCastException,尤其是 Android 或 Spring Boot 类型的封闭分发场景。
- 你在构建一个 SDK 或 aar,要求所有接入方无论怎么写依赖,最终打包进去的 Jackson 必须是 2.16.1 —— 只能用
enforcedPlatform - CI 流水线里发现某第三方库偷偷引入了
jackson-databind:2.12.7,而你的主逻辑依赖 2.16+ 的新 API,这时加enforcedPlatform才能确保裁决结果唯一 - 它会重写所有依赖路径的 version 字段,哪怕那个版本来自 transitive 依赖链的第 5 层,也会被强制替换
- 副作用明显:如果 BOM 里锁的是
jackson-core:2.16.1,但某个库内部硬编码调用了2.15.0特有的包私有方法,enforcedPlatform不会报错,但运行时仍可能崩
常见错误:把 platform 当 enforce 用,结果线上闪退
最典型的误用场景是 Android 项目里为解决 Jackson 冲突只加了 platform,却没意识到 OkHttp、Retrofit、Spring Boot Starter 这些库各自带的传递依赖版本差异极大,而 platform 根本压不住它们之间的冲突。
- Gradle 日志里看到
Selected primary variant of com.fasterxml.jackson.core:jackson-databind:2.15.2,不代表它真进了 APK —— 得用./gradlew app:dependencies --configuration releaseRuntimeClasspath确认实际解析结果 -
enforcedPlatform不会改变compileClasspath的编译期行为,但会改runtimeClasspath和最终打包内容,这点容易被忽略 - Android Gradle Plugin 8.5+ 对
enforcedPlatform的处理更严格,若 BOM 中某 artifact 在当前仓库不可达,构建直接失败,不像旧版默默跳过
enforcedPlatform,如果 BOM 里定义的版本之间存在二进制不兼容(比如 mix 了 Jackson 2.15 和 2.16 的 patch 版本),问题只是从“不确定哪个版本胜出”变成“确定用了一个错的版本”。


















