什么是依赖管理
软件很少独立工作。在大多数情况下,项目都要依赖于lib形式的可重用功能,还有就是项目可能被切分成多个单独的模块来构成模块化系统。依赖管理是一种可以让项目可以自动化得定义,解析,使用依赖的技术。
Gradle中的依赖管理
Gradle内置支持依赖管理,并且实现了现代软件项目的各种典型的场景。之后的几章会通过示例项目来讲解依赖管理的主要概念,下面的图可以让大家有个模糊的概念
示例项目是个java项目,源码中用到了Google Guava
的一些类,除了Guava之外,还需要JUnit来编译和执行测试代码
Guava和JUnit就可以当做这个项目的依赖,在构建脚本中开发者可以把依赖定义到不同的范围中,比如编译源码或者执行测试。在Gradle中依赖的范围叫做配置,
同城依赖是以模块方式出现的,你需要指定Gradle在哪里找这些模块,以便构建可以使用它们。存储模块的地方就叫做资源库。定义了资源库之后,Gradle就知道怎么样查找和检索模块。资源库有两种方式:本地库和远程库。
在运行时,如果相应的任务需要,那么Gradle就需要定位依赖的声明,依赖可能需要从远程库下载,也可能从本地库检索或者是在多项目构建中的其他项目。这个过程就叫做依赖解析
一旦解析,解析机制就会存储依赖的底层文件作为本地缓存,可以叫做依赖换成,之后的构建会重用这些文件,而不用再到远程库下载。
模块还能提供一些其他的元数据,元数据是描述模块更详细信息的数据,比如在资源库中的坐标,项目的信息,模块的作者。在元数据中,模块可以定义它运行需要的其他模块,比如JUnit 5 platform
需要平台公共模块,Gradle可以自动处理这些额外的模块,这叫做依赖传递,如果需要你还可以自定义依赖传递的行为。
项目如果有几十个或者上百个依赖时,那就会非常痛苦,在build scan
和内置任务的帮助下,Gradle提供了足够的工具来可视化,导航和分析依赖图谱,
依赖如何解析
Gradle使用你的依赖声明,资源库声明来下载所有依赖项的过程叫做依赖解析,下面是依赖解析的简要步骤:
- 对于指定的依赖,Gradle会通过搜索依赖相关的模块来解析依赖。每个库都会依次查找,按照库的类型不同,Gradle会找到模块对应的元数据文件(
.module
,.pom
,ivx.xml
)或者直接查找构件。
- 如果依赖的版本是动态的(比如
1.+
),Gradle会解析成相应最高版本的固定版本。对于Maven来说是用maven-metadata.xml
完成的 - 如果模块的元数据是POM文件,并且有父POM文件,Gradle会递归解析每一个父POM文件。
- 如果依赖的版本是动态的(比如
- 一旦多个资源库都搜索到了对应的模块,那么Gradle将会找到一个最佳的,规则如下:
- 对于动态版本,优先选择高版本
- 有模块原数据文件的优先于只有构件文件的
- 前面定义的库优先于后面定义的库
- 当在依赖在一个资源库中找到了固定版本且有元数据文件,那么就不会再往下查找
- 从上述的资源库中请求该模块所有的构件。