了解本地依赖缓存
到目前为止,我们已经讨论了如何声明依赖项并配置各种类型的存储库来解决这些工件。 Gradle 自动确定您要执行的任务是否需要依赖项,从存储库下载工件,并将它们存储在本地缓存中。 任何后续构建都将尝试重用这些工件。 在本节中,我们将通过分析缓存结构、确定缓存在幕后的工作原理以及如何调整其行为来进行更深入的研究。
分析缓存结构
让我们通过 Cargo 库的示例来探索本地缓存结构。 您知道 Gradle 在运行部署任务时下载了 JAR 文件,但它把它们放在哪里了? 如果你查看 Gradle 论坛,你会发现很多用户经常询问它。 您可以使用 Gradle 的 API 来查找。 以下清单显示了如何打印分配给配置货物的所有依赖项的完整串联路径。
task printDependencies << {
configurations.getByName('cargo').each { dependency ->
println dependency
}
}
如果运行该任务,您将看到所有 JAR 文件都存储在目录 /Users/ benjamin/.gradle/caches/artifacts-15/filestore 中:
$ gradle -q printDependencies
/Users/benjamin/.gradle/caches/artifacts-15/filestore/
➥ org.codehaus.cargo/cargo-core-uberjar/1.3.1/jar/
➥ 3d6aff857b753e36bb6bf31eccf9ac7207ade5b7/cargo-core-uberjar-1.3.1.jar
/Users/benjamin/.gradle/caches/artifacts-15/filestore/
➥ org.codehaus.cargo/cargo-ant/1.3.1/jar/
➥ a5a790c6f1abd6f4f1502fe5e17d3b43c017e281/cargo-ant-1.3.1.jar
该路径在您的计算机上看起来可能略有不同。 让我们进一步剖析这条道路并赋予它更多的意义。 Gradle 在本地缓存中存储依赖项的根目录是 <USER_HOME>/.gradle/caches。 路径的下一部分,artifact-15,是特定于 Gradle 版本的标识符。 需要区分元数据存储方式的变化。
请记住,此结构可能会随着 Gradle 的新版本而改变。 实际的缓存分为两部分。 子目录 filestore 包含从存储库下载的原始二进制文件。 此外,您还会发现一些存储有关下载的工件的元数据的二进制文件。 您在日常工作中永远不需要查看它们。 以下目录树显示了本地依赖项缓存根级别的内容:
.
└── artifacts-15
├── artifact-at-repository.bin
├── artifact-at-url.bin
├── artifacts-15.lock
├── dynamic-revisions.bin
├── filestore // 包含原始构件目录
│ └── org.codehaus.cargo
│ └── cargo-ant
│ └── 1.3.1
│ ├── jar
│ │ └── a5a790c6f1abd6f4f1502fe5e17d3b43c017e281
│ │ └── cargo-ant-1.3.1.jar
│ └── pom
│ └── cf13fc6a9e07971c96f0e2cc3c726fe6473eb926
│ └── cargo-ant-1.3.1.pom
├── module-metadata
│ └── ...
└── module-metadata.bin
文件存储目录是依赖关系的自然表示。 属性组、名称和版本直接映射到文件系统中的子目录。 在下一节中,我们将讨论 Gradle 缓存为您的构建带来的好处。
显着的缓存功能
Gradle 尝试减少远程存储库的网络流量。 这不仅适用于已下载的依赖项。 如果无法在存储库中解析依赖关系,则此元数据将存储在缓存中。 Gradle 使用此信息来避免每次构建运行时都必须检查存储库。
减少工件下载并改进变更检测
Gradle 提供与 Maven 本地存储库的紧密集成,以避免下载现有工件。 如果依赖关系可以在本地解决,那么它就会被重用。 对于使用其他版本的 Gradle 存储的工件也是如此。
Gradle 通过比较本地和远程校验和来检测存储库中的工件是否已更改。 未更改的工件不会再次从本地缓存下载和重用。 想象一下存储库中的工件已更改,但校验和仍然相同。 如果存储库管理员用相同版本替换工件,则可能会发生这种情况。 最终,您的构建将使用该工件的过时版本。 Gradle 的依赖管理器试图通过考虑附加信息来消除这种情况。 例如,它可以通过比较 HTTP 标头参数 content-length 的值或最后修改日期来确保工件的唯一性。 这是 Gradle 的实现相对于 Ivy 等其他依赖管理器的优势。