前言
本篇文章介绍自动化构建概念以及相关工具,简单介绍Ant
、Ivy
和Maven
,以及我们的主角 Gradle
。读完这篇文章,你会了解一小段关于项目构建的发展历史,完善对项目构建的认知,以及为什么会出现Gradle
,Gradle
能做什么。如果你觉得这些都已经了解了,那么可以直接去 Gradle官网 学习更多知识~
本篇文章结合自己的认知,总结《实战Gradle》1-2章的理论内容,如有不当或者过时、可优化的地方,麻烦指正,谢谢~。
自动化构建
在很久以前,人们打包项目都是手动的,通过一些特定的步骤最终产生用来运行的程序包,后来,自动化构建出现了,它极大地提升了生产效率。
它的优点有:
- 过程自动化,一键调用,不易出错且可重复利用
- 优秀的自动化构建,可以脱离机器的限定,可在任何时间、任何机器上运行。
项目自动化的类型大致分为以下几种:
- 按需构建:执行一部分预定义的构建过程(比如:编译源码、移动文件、组装软件)。一般会使用版本控制系统(VCS: Version Control System)来管理构建定义的版本与源码文件。
- 触发构建:由一次代码提交触发构建。通常敏捷开发中都会这么做。
- 预定构建:在预定时间下进行构建。比如每天凌晨5点进行构建,一般用于生成报告或者一些文件。
触发构建与预定构建通常也叫做持续集成(CI: Countinuous Integration)
构建工具
构建工具与任务
你可能会有一个问题:一个shell
脚本就可以做到自动化构建了,为什么要专门定义一个工具?
首先,一个shell
脚本确实可以实现一个可重复利用、稳定可靠的构建。但是,它的可移植性不强,我们还是需要一个通用的工具,能在各个系统上运行。
这个工具是什么样的呢?它是一个可编程的工具,能够让你定义有序的任务去实现自动化需求。有序任务是什么样的呢,看下面这个例子:

在数据结构定义中,这是一个有向非循环图,它包含两个元素:
- 节点:一个工作单元(只能被执行一次)
- 有向边:表示节点的关系(这里表示依赖关系,比如上图中步骤2依赖于步骤1)
构建工具的基本组成元素
- 构建文件:它包含了构建所需的外部信息以及外部依赖。
- 构建的输入和输出:比如将源代码作为输入,输出结果为可交付的软件
- 构建引擎:用于处理构建文件。
- 依赖管理器:比如在build文件中声明的依赖定义,从工件仓库(本地文件系统、FTP、远程仓库等)中解析获取(比如jar文件),并使用在项目中。

Java的构建工具
构建工具一般都是可编程的工具(强调一下~),那么Java中常见的构建工具有哪种呢,下面介绍最流行的两种。
Apache Ant
Ant
的基本编程元素有task
、target
、project
,使用XML编写。
task
:一段可执行的代码。target
:task
集合,target
可以依赖target
。project
:顶级元素,包含一个或多个target
。

Ant
的优点是灵活性高,你可以随意定义task
,再组装成target
,并规定task
之间的依赖。但是Ant
有以下缺点:
- 正因为这种自由性,并且没有统一的指导规范,导致
Ant
在面对复杂逻辑的时候难以维护,XML
也会过于臃肿。 - 没有暴露任何API可以使用。
- 没有文件依赖管理系统(在没有
Ivy
的情况下难以管理外部依赖)
Apache Maven
Maven
在如今的后台项目中经常见到,它算是站在Ant
的肩膀上出现的,鉴于Ant
的一些缺点,Maven
做了改进。
设置默认值(基于约定犹豫配置的思想)
Maven
给项目配置提供了默认值,以减少XML的臃肿,对,Maven
也是使用XML
编写的,如果你都接受Maven
的默认值,你的配置文件只需要很少的行数;
构建生命周期
Maven
同时也引入了构建生命周期的思想,规定了构建过程中必要步骤:
- 编译源代码
- 运行单元测试和集成测试
- 组装文件(例如jar文件)
- 将文件部署到本地仓库
- 将文件发布到远程仓库
以上过程在Maven
构建的时候会有序地执行,这些既有约定给了Maven
规范性,不像Ant
的构建文件会难以阅读,但同时也造成了Maven
的局限性。下图是Maven
重要的构建生命周期阶段,也是一些我们常用的命令:

依赖管理
Ant
是没有依赖管理的,但是Maven
有。Maven Central
是Java
社区中最流行的二进制仓库。(在提供依赖管理的同时,还提供了项目的多模块管理)

Maven插件
提供很多插件,如果你想打破Maven
的一些已有约定,就要使用Mojo
编写自定义插件,但是在Maven
中写插件是累赘且非常复杂的。
Gradle

“让不可能成为可能,让可能变得简单,让简单变得优雅”——Gradle座右铭
面对日益复杂的软件工程构建需求,Maven
有如下缺点:
- 因需要遵循它既有的约定,所以无法满足项目构建的灵活性需求;
- 其使用的
XML
语言并不具有很强的表达性,难以定义复杂的定制逻辑; - 面对多语言编程构建的需求更加多样化,比如
JavaSript
需要被合并、压缩,服务器代码需要被编译、打包和部署,Maven
也经不够给力了。
此时 Gradle 应运而生,它有以下优点:
- 基于
JVM
的构建工具,可以使用 Groovy 或 Kotlin 进行编写。可以描述非常复杂的逻辑。 - 强大的
API
系统。暴露生命周期方法,高度自定义,以及提供了两个方便使用的配置模块(开箱即用):repositories
&dependencies
,可以定义依赖以及远程仓库。并且还有灵活的命令行API
。 - 灵活的约定。遵循基于约定的构建方式,开发人员并不需要知道它是怎么工作的,只需要把精力集中在配置上。(当年小看Gradle的原因原来就是它的设计太好了嘤嘤嘤......)
- 强大的依赖管理系统。
Gradle
有自己的一套可配置、可靠的和有效的依赖管理方案。 - 强大的插件系统。插件实现起来简单,并且可以让你完全访问
Gradle
的API
,而且可以像其他软件一样编写、测试和发布。 - 可以与其他构建工具集成。他能完美兼容
Ant
、Ivy
与Maven
,可以让你在感受Gradle
特性的同时,小步地迁移。(这句话好优雅) - 可拓展的构建。支持增量构建、部分构建,而不是直接执行clean工作,使构建更迅速。
- 多项目构建。可以模块化项目,组装多项目构建。
- 多语言构建。不仅可以构建
Java
项目,还能构建Web
、C++
项目等。
并且Gradle
基于 Apache License 2.0 在 Github上开源,拥有非常活跃的 社区。
还有一些额外特性,比如 Gradle包装器,丰富的命令行接口,驼峰缩写调用(比如runMyAwesomeTesk
可以使用rMAT
命令进行调用)等等,并且,它是Android
的官方构建语言。
如果你要开始Gradle
的学习,我更建议从 官网 下手,毕竟官网都是最新资料
安装Gradle
安装过程很简单,我使用的是Windows
环境,下载→解压→配置环境变量,再命令行验证一下:

运行Gradle脚本
每个Gradle
构建都是以一个脚本开始的,当运行命令行命令的时候,Gradle会默认读取当前目录下的build.gradle
文件(找不到则会报错)。
接下来写一个简单的 hello world 的例子。在D盘下创建test目录,在该目录下创建build.gradle
文件,写入如下代码并运行:

.gradle为自动生成的文件;-q
代表quiet,只输出该task相关的信息;hello
是task
的名称。看到这里,你的Gradle
已经入门啦,我们再看一个例子,修改原来的代码为:
// 创建1个task
task startSession {
chant()
}
// 定义方法
def chant() {
ant.echo(message: 'Repeat...')
}
// 创建3个task
3.times {
task "myTask$it" {
println "Gradle Task --- $it"
}
}
// 规定依赖
myTask0.dependsOn startSession
myTask2.dependsOn myTask0, myTask1
task groupTherapy(dependsOn: myTask2)
接下来执行所有task
:

上图最前面是输出结果,下面将所有task
都分类列出,可以看到我们定义的task
与系统自带task
。
现在,你对Gradle
应该有一定的认识了,如果想学习更多,请到官网学习吧~
补充
发现很多写Android
的童鞋还不知道使用Maven
库,这里补充下,一般大家可以到MavenRepository上去寻找自己想要的库,举个例子,我想要xml
转换的相关库,我找到了JAXB
的库:

我们可以看到有很多相关的构建工具的引用,不仅是Maven
,还有前面提到的Ivy
,剩下的大家有兴趣可以去研究研究。最后我们复制Gradle
下面的代码放到项目中,就能愉快地使用啦~