gradle基础+Groovy描述笔记(一)

最近逛B站发现一个很棒的关于gradle的教程,主要分为三集分别讲解了gradle基础,构建,插件编写和实际插件分析,全部学习下来对gradle有了初步的了解,也极大帮助了我看gradle构建项目的文件,下面把我学习后的总结写一个笔记记录一下。

这个视频地址是https://www.bilibili.com/video/BV1DE411Z7nt?from=search&seid=10664365719681234245,作者是“硬核空间Java”,讲得非常好推荐有兴趣的朋友可以前往学习。

这篇笔记也以下面的结构进行学习,针对gradle中一些重要的概念进行归纳结合windows7进行一些拓展:

(1)gradle基础概念
         -- Distribution
         -- Wrapper
         -- GradleUserHome
         -- Daemon
(2)Groovy:
         -- 动态调用与MOP
         -- 闭包
(3)gradle构建
         -- 核心模型
         -- Project
         --Task
         -- Lifecycle与Hook
(4)插件编写
         -- 构建逻辑的复用
         -- 简单插件
         -- script插件
         -- buildSrc插件
         -- 发布的插件
(5)实际插件分析

gradle基础概念。

一.什么是gradle?

gradle基础+Groovy描述笔记(一)

从百度百科可以看出gradle是一种构建项目的工具,和maven类似,都是由java编写基于jvm运行,gradle中/lib目录下有很多jar就是gradle运行所需的java运行文件,支持IntelliJ,Eclipse, Android Studio等开发工具。gradle的版本更新速度很快,可在https://services.gradle.org/distributions/官网中看到更新的频率非常频繁:

gradle基础+Groovy描述笔记(一)

上面是关于gradle的介绍,在gradle中有几个比较重要的概念,分别是Distribution,Wrapper,GradleUserHome和Daemon。

(一)Distribution:这个就是gradle的版本信,如上https://services.gradle.org/distributions/不同的版本会有自己的特性。

(二)Wrapper:从官方文档https://docs.gradle.org/current/userguide/gradle_wrapper.html可以看到,Wrapper是一个可以声明gradle版本的脚本,当项目需要的时候可以自动下载声明的gradle版本并解压到GradleUserHome中,从而节约开发时间成本。

gradle基础+Groovy描述笔记(一)

gradle wrapper的工作流程如上:先自动下载一个声明的gradle版本到服务中,解压这个版本到GradleUserHome,然后供gradle项目使用这个版本特性。上述官网提供了本地构建过程的实例,可以进行演示:

(1)首先新建一个项目文件夹,如gradle-demo,在这个项目中只创建一个build.gradle,build.gradle中暂时不写任何内容。

然后再这个项目中通过gradle wrapper启动一个wrapper,执行成功后会在项目中自动生成一些文件:

gradle基础+Groovy描述笔记(一)

gradle基础+Groovy描述笔记(一)

结构如下:

├── build.gradle
├── settings.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat

(2)在gradle-wrapper.properties文件中distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip

声明这个wrapper关联一个gradle-6.3-bin的Distribution,

gradle基础+Groovy描述笔记(一)

(3)接下来执行gradle wrapper --gradle-version 6.3 --distribution-type all

gradle基础+Groovy描述笔记(一)

$ gradlew.bat build
Downloading https://services.gradle.org/distributions/gradle-5.0-all.zip
.....................................................................................
Unzipping C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-all\ac27o8rbd0ic8ih41or9l32mv\gradle-5.0-all.zip to C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-al\ac27o8rbd0ic8ih41or9l32mv
Set executable permissions for: C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-all\ac27o8rbd0ic8ih41or9l32mv\gradle-5.0\bin\gradle

BUILD SUCCESSFUL in 12s
1 actionable task: 1 executed

关联了wrapper之后,可以使用gradlew.bat进行构建:gradlew.bat build,一开始并没有这个版本的Distribution,会先进行download,下载结束后会进行Unzipping解压操作,最后会进行Set executable permissions操作将Distribution设置到GradleUserHome中使特性生效,这个过程完成后这个项目随意转移,保证各个人下载项目都是同一个gradle版本构建避免版本不一致对项目的影响,详细操作说明见上述wrapper的官方文档。

(三)GradleUserHome:这个是与gradle交互的一个重要目录,默认在$USER_HOME/.gradle目录,用于存储全局配置信息,初始化脚本,缓存目录等,一般可以在环境变量配置这个地址,其中init.d文件可以设置国内阿里云等数据源对资源进行加速,详细描述可参考https://docs.gradle.org/current/userguide/directory_layout.html#dir:gradle_user_home

gradle基础+Groovy描述笔记(一)

(四)Daemon:这个是最重要的一个点,涉及到了gradle的构建原理和过程,这里通过图文方式,与maven对比,同时用

./gradlew compileJava任务为例以图的方式展示其构建过程:

对maven构建来说:

gradle基础+Groovy描述笔记(一)

maven开始构建时会启动一个jvm,所有的任务都交由这个jvm去处理,直到所有任务处理完成才结束整个构建工作,这种方式带来的问题就是构建时间缓慢。

对gradle来说:

gradle基础+Groovy描述笔记(一)

gradle在构建时,会先在后台启动一个Daemon JVM,这个进程用于接收gradle client的具体构建请求进行相应的构建任务,

gradle client运行一个轻量的jvm,只发送构建任务的请求,Daemon接收并完成这个请求任务后会自动销毁这个client;Daemon进程一般会一直处于热状态(即不需要每次都进行冷启动),当一个新的client任务请求到达时可以直接进行任务处理进而节约时间开销。Daemon与Client会存在一个兼容性问题,如daemon的版本或运行空间大小与client存在不匹配的情况,就可以采用兼容性策略,如当daemon启动一段时间若一直处于空闲状态则自动销毁该Daemon。

下面结合./gradlew compileJava 展示构建任务的过程如下所示:

gradle基础+Groovy描述笔记(一)

上面是关于 gradle基础和重要概念的描述,有助于了解gradle的结构和工作方式。由于在一些gradle项目的build.gradle文件中,经常会看到类似Plugins,Task等关键词,这里就引出了Groovy或Kotlin,这两种类似这里只对Groovy的动态调用与MOP以及闭包概念进行大概描述,这里大概了解Groovy便于更好理解build.gradle文件,具体的Groovy细节不作深入了解有兴趣可以查询相关书籍或文档。

Groovy:是运行在JVM上的强类型动态调用脚本语言,与Kotlin类似。

(1)动态调用与MOP:运行时调用如new A(a:1).printA(),MOP如def a = new A(a:1)

(2)闭包:这个概念比较重要在build.gradle中也几乎处处体现,闭包也是DSL的核心,Groovy中可以像def closure = {xxxxxxx}定义一个方法然后直接调用closure(),这个closure内的东西就可以理解成闭包,在gradle中如TASK,Plugins,buildScript等都体现了这个闭包的概念,如buildScript{ext{xxxx}}:相当于调用了buildScript方法传递ext闭包参数,这个buildScript方法可以在Gradle源码API的Project中找到对应功能描述。

由于篇幅原因,笔记(一)只记录gradle和groovy的一些概念,对于gradle构建,插件编写和实际插件分析将在笔记(二)中进一步讨论。