Gradle默认不拉新SNAPSHOT是因为将-SNAPSHOT视为changing module,默认缓存24小时且不主动检查远程maven-metadata.xml;即使远程已更新,本地仍复用缓存元数据,除非显式配置cacheChangingModulesFor 0, 'seconds'或使用--refresh-dependencies。

Gradle为什么默认不拉新SNAPSHOT
Gradle对SNAPSHOT版本的处理和Maven不同:它不会自动检查远程仓库是否有更新,而是默认缓存24小时。哪怕Nexus或Artifactory上已部署了新的mylib-1.0.0-SNAPSHOT.jar(带新时间戳),本地构建仍可能继续用旧缓存——这不是bug,是设计行为。
根本原因在于Gradle把-SNAPSHOT当作“changing module”,但它的缓存策略默认是cacheChangingModulesFor 24, 'hours',且这个策略只在首次解析依赖时生效,后续构建直接复用缓存元数据。
- 即使你改了
build.gradle里的version字符串,只要还是1.0.0-SNAPSHOT,Gradle就认为是同一个changing module -
mavenLocal()如果被配置在repositories里靠前位置,会优先命中本地Maven仓库的旧快照,跳过远程检查 - Gradle不会像Maven那样读取
maven-metadata.xml去比对最新时间戳;它依赖自己的缓存校验逻辑
强制刷新SNAPSHOT的三种有效方式
以下方法按推荐顺序排列,优先选长期可控的方案:
- 在
build.gradle中全局启用秒级刷新:configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' }注意:必须放在allprojects或subprojects块内,不能只写在某个模块的dependencies里 - 命令行临时强制更新:
./gradlew build --refresh-dependencies。这个会绕过所有缓存,但每次都要加参数,不适合CI - 显式声明
changing = true(仅对单个依赖):implementation('com.example:lib:1.0.0-SNAPSHOT') { changing = true }注意:仅对该依赖生效,且需配合cacheChangingModulesFor 0, 'seconds'才可靠;单独写changing = true在某些Gradle版本中无效
仓库配置错误导致SNAPSHOT“隐身”
常见现象是明明配了私有仓库URL,却始终从mavenCentral()或google()拉包,而这些公共仓库根本不托管你的SNAPSHOT。
- 检查
repositories声明顺序:Gradle按顺序查找,一旦在某个仓库命中坐标(哪怕只有旧POM),就不会继续往后查。把私有仓库放在mavenCentral()之前 - 禁用
mavenLocal():如果本地Maven仓库存在同名SNAPSHOT,mavenLocal()会直接返回它,完全跳过远程。开发阶段建议注释掉这行 - 确认私有仓库URL末尾路径正确:比如
https://nexus.example.com/repository/maven-snapshots/,结尾斜杠不能少,否则元数据路径拼接失败 - 不要在
mirrorOf *镜像配置中开启snapshots:这会把所有仓库的SNAPSHOT请求都路由过去,但镜像本身可能没同步快照
缓存损坏或残留引发的“假不更新”
Gradle缓存不是原子更新,网络中断或权限问题可能导致部分文件写入失败,造成元数据与JAR不一致。此时即使强制刷新,Gradle仍可能因校验失败而回退到旧版本。
- 定位缓存目录:
$HOME/.gradle/caches/modules-2/files-2.1/com.example/lib/1.0.0-SNAPSHOT/ - 删干净整个
1.0.0-SNAPSHOT子目录(不只是JAR,包括.module、.pom、哈希目录),再执行./gradlew --refresh-dependencies - 避免手动删错:不要进
modules-2/metadata-2.x目录乱删,那里是全局元数据索引,删错会导致整个缓存失效 - CI环境务必配置
--no-daemon和--refresh-dependencies,防止守护进程复用损坏缓存
实际项目里最常被忽略的是:**Gradle的SNAPSHOT刷新机制和Maven的updatePolicy没有对应关系**。你在settings.xml里配了always,对Gradle完全无效。必须在Gradle自身的配置里动手,而且得配对位置、配对作用域、配对缓存策略——三者缺一不可。











