有道无术,术尚可求,有术无道,止于术。
在Gradle 中,build.gradle是最核心的文件,这个文件就是Gradle 中的一个Project对象实例,项目中每个模块都会有一个build.gradle文件。
Project接口中的属性和方法就对应了文件中的配置,此接口是用于从构建文件与 Gradle 交互的主要 API。
Project API

Project和build.gradle 文件之间存在一对一的关系。在构建初始化期间,Gradle为每个参与构建的项目组装一个Project对象,步骤如下:
settings实例,一个settings实例就是一个settings.gradle文件,多模块时,只有根项目才有这个文件settings实例的配置,按配置层次扫描并解析配置在 settings.gradle中的所有模块,创建 Project实例的层次结构build.gradle进行初始,并创建Projecte 实例,项目按广度顺序进行评估,因此根项目在其子项目之前进行加载比如下方示例中,会根据 settings.gradle中配置的子父工程依次进行实例化:

Project有很多属性,有默认也有自定义的。
比如,我们可以直接在build.gradle文件中获取属性,name属性就表示当前工程名称,我们可以通过以下几种方式获取。
println("name:"+name)
println("name:"+project.name)
println(project.property("name"))
可以在官网中查看Project的所有默认属性,常用的有:
| 属性 | 描述 |
|---|---|
| allprojects | 包含此项目及其子项目的集合。 |
| buildDir | 当前项目的编译目录(自动生成)默认值 porjectDir/build |
| defaultTasks | 当前项目的默认任务的名字集,当前构建没有提供任务名时会执行这些默认任务 |
| group | 当前项目的组名 |
| logger | 当前项目的日志器,可以用来在 build 文件中写日志 |
| name | 此项目的名称 |
| parent | 此项目的父项目 |
| path | 这个项目的绝对路径 |
| project | 当前project对象实例 |
| rootDir | 本项目的根目录。根目录是根项目的项目目录 |
| rootProject | 当前项目层次结构中的根project |
| subprojects | 当前项目的子项目的集合 |
| tasks | 本项目的task集合。 |
| version | 此项目的版本 |
自定义扩展属性时必须通过ext命名空间定义。一旦定义了一个额外的属性,它就可以直接在拥有的对象上使用(比如当前项目、任务和子项目),并且可以读取和更新。
比如可以在扩展属性中定义一个依赖的版本号,然后在版本配置中,引用该属性作为版本号:
ext {
bootVersion = '2.6.8'
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-web:${bootVersion}"
}
属性是有作用域的,读写属性时,Project会按照下面范围的顺序进行查找的,在某个范围找到属性后就会返回该属性。如果没有找到,会抛出异常。
Project还有很多方法,可以直接在build.gradle中编写方法,比如上篇文档我们介绍的dependencies {}添加依赖,实际就是调用的Project中的方法,可以直接按住Ctrl+右键点进去,可以看到该方法参数就是一个groovy 闭包。

常用的方法如下所示:

buildscript{}的作用是为运行脚本提供依赖或信息支持。
假设要执行一项指令./gradlew buildImage构建docker镜像,而Gradle官方自身没有,则需要依赖到maven库下载或需要调用第三方插件,这时候就需要在buildscript中指定docker的依赖即可。
buildscript {
repositories {
mavenLocal()
maven {
url "https://maven.aliyun.com/repository/public"
}
mavenCentral()
}
dependencies {
classpath "com.bmuschko:gradle-docker-plugin:3.3.4"
classpath "org.springframework.boot:spring-boot-gradle-plugin:2.6.5"
}
}
configurations{} 官网的解释是依赖项的分组配置,在上一篇文档中,我们了解到依赖的是有作用范围的,根据不同的configuration划分到不同的分组中。
比如下图示例中,Gradle会从中央存储库下载依赖,然后根据不同的configuration分组将依赖添加到不同的组中,比如分组是implementation则只用于编译源码,testImplementation只用于Test 目录中。

这些分组配置,是由java 插件提供的,如果去掉改插件,是会报错找不到implementation。

Java 插件为您的项目添加了许多依赖配置:
main 源码目录依赖配置如下图所示:

test 目录依赖配置如下图所示:

configurations支持继承,比如testImplementation就继承自implementation,如下所示:

configurations还支持自定义,比如下方案例中,我们定义一个配置分组,然后将该分组的依赖移入到某个文件夹中:
configurations {
myconf
}
dependencies {
myconf 'com.alibaba:fastjson:1.2.58'
}
// afterEvaluate:可以添加一个闭包,它会在项目完成评估后立即执行。
// 当执行属于该项目的构建文件时,会通知此类监听器。
afterEvaluate {
// 打印 myconf 分组的第一个依赖文件
println configurations.myconf.files.first()
// 打印路径
println configurations.myconf.asPath
// 移入路径
def libPath = projectDir.absolutePath + "/src/main/lib2"
// 复制 依赖到 libPath中
copy {
from configurations.myconf.files.first()
into libPath
}
}
repositories{}用于配置依赖仓库,参考上一篇
dependencies{}用于配置依赖,参考上一篇
allprojects{}用于配置项目及其每个子项目所需要的依赖。一般在多模块项目场景下我们会把公共的部分配置在根项目的allprojects中。
如下所示:
allprojects {
// 配置共用插件
apply plugin: "idea"
apply plugin: "id"
apply plugin: "maven"
apply plugin: "war"
apply plugin: "com.bmuschko.docker-remote-api"
apply plugin: "org.springframework.boot"
// 配置共用存储库
repositories {
mavenLocal()
maven {url "https://maven.aliyun.com/repository/public"}
mavenCentral()
}
// 配置共用依赖
dependencies {
}
}
subprojects{}和allprojects{}差不多,但是它只作用于子项目,当前项目则无效
sourceSets{} 用于配置此项目的源码集,默认的源码结构如下:

可以修改源码的结构,但是一般都不会改,如下所示:
sourceSets {
// 将main.java目录修改,
main {
java {
srcDir 'thirdParty/src/main/java'
}
}
}
还可以排除某个文件或目录,如下所示:
plugins {
id 'java'
}
sourceSets {
main {
java {
exclude 'some/unwanted/package/**'
}
}
}
还可以指定源码的输出目录,如下所示:
sourceSets {
main {
output.resourcesDir = output.classesDir = '/WEB-INF/classes/'
java.srcDir('src')
resources.srcDir('src')
}
}
artifacts{}用于配置交付产品组件信息,比如jar 或者war 包都是一个交互产品,具体用法,后面单独介绍。
publishing{}用于发布当前项目到仓库,具体用法,后面单独介绍。