Gradle学习之基本语法入门

请通过以下方式下载本系列文章的Github示例代码:
git clone https://github.com/davenkin/gradle-learning.git
 
 
Gradle是一种声明式的构建工具。在执行时,Gradle并不会一开始便顺序执行build.gradle文件中的内容,而是分为两个阶段,第一个阶段是配置阶段,然后才是实际的执行阶段。在
配置阶段,Gradle将读取所有build.gradle文件的所有内容来配置Project和Task等,比如设置Project和Task的Property,处理Task之间的依赖关系等。
 
虽然很多时候我们只需要照着网上的例子写自己的DSL语句就行了,但是此时我们所知道的也就只有这么多了。如果我们能够了解Gradle DSL的内部工作机制,那么我们便可以达到
举一反三的效果。在前面的文章中我们讲到,Gradle的DSL只是Groovy语言的内部DSL,也即必须遵循Groovy的语法规则。现在,让我们先来看看以下非常简单的Task:
 
task showDescription1 << {   
  description = 'this is task showDescription'   
  println description
}
task showDescription2 << {   
  println description
}
showDescription2.description = 'this is task showDescription'
task showDescription3 << {   
  println description
}
showDescription3 {   
  description = 'this is task showDescription'
}
 
 
以上3个Task完成的功能均相同,即先设置Task的description属性,在将其输出到命令行。但是,他们对description的设置方式是不同的。对于showDescription1,我们在定义一个Task的同时便设置description;对于showDescription2,其本身便是Project的一个Property;而对于showDescription3,我们是在一个和它同名的方法中设置description。
 
事实上,对于每一个Task,Gradle都会在Project中创建一个同名的Property,所以我们可以将该Task当作Property来访问,showDescription2便是这种情况。另外,Gradle还会创建一个同名的方法,该方法接受一个闭包,我们可以使用该方法来配置Task,showDescription3便是这种情况。

要读懂Gradle,我们首先需要了解Groovy语言中的两个概念,一个Groovy中的Bean概念,一个是Groovy闭包的delegate机制。
 
Groovy中的Bean和Java中的Bean有一个很大的不同,即Groovy为每一个字段都会自动生成getter和setter,并且我们可以通过像访问字段本身一样调用getter和setter,比如:
 
class GroovyBeanExample {   
  private String name
}
def bean = new GroovyBeanExample()
bean.name = 'this is name'
println bean.name
 
我们看到,GroovyBeanExample只定义了一个私有的name属性,并没有getter和setter。但是在使用时,我们可以直接对name进行访问,无论时读还是写。事实上,我们并不是
在直接访问name属性,当我们执行"bean.name = 'this is name'"时,我们实际调用的是"bean.setName('this is name')",而在调用"println bean.name"时,我们实际调用的是
"println bean.getName()"。这里的原因在于,Groovy动态地为name创建了getter和setter,采用像直接访问的方式的目的是为了增加代码的可读性,使它更加自然,而在内部,Groovy依然
是在调用setter和getter方法。这样,我们便可以理解上面对showDescription2的description设置原理。
 
另外,Gradle大量地使用了Groovy闭包的delegate机制。简单来说,delegate机制可以使我们将一个闭包中的执行代码的作用对象设置成任意其他对象。比如:
 
class Child {   
  private String name
}
class Parent {   
  Child child = new Child();   
  void configChild(Closure c) {      
     c.delegate = child      
     c.setResolveStrategy Closure.DELEGATE_FIRST      
     c()   
  }
}
def parent = new Parent()
parent.configChild {
  name = "child name"
}
println parent.child.name
 
 
在上面的例子中,当我们调用configChild()方法时,我们并没有指出name属性是属于Child的,但是它的确是在设置Child的name属性。事实上光从该方法的调用中,我们根本不知道name是属于哪个对象的,你可能会认为它是属于Parent的。真实情况是,在默认情况下,name的确被认为是属于Parent的,但是我们在configChild()方法的定义中做了手脚,使其不再访问Parent中的name(Parent也没有name属性),而是Child的name。在configChild()方法中,我们将该方法接受的闭包的delegate设置成了child,然后将该闭包的ResolveStrategy设置成了DELEGATE_FIRST。这样,在调用configChild()时,所跟闭包中代码被代理到了child上,即这些代码实际上是在child上执行的。此外,闭包的ResolveStrategy在默认情况下是OWNER_FIRST,即它会先查找闭包的owner(这里即parent),如果owner存在,则在owner上执行闭包中的代码。这里我们将其设置成了DELEGATE_FIRST,即该闭包会首先查找delegate(本例中即child),如果找到,该闭包便会在delegate上执行。对于上面的showDescription3,便是这种情况。当然,实际情况会稍微复杂一点,比如showDescription3()方法会在内部调用showDescription3的configure()方法,再在configure()方法中执行闭包中的代码。

你可能会发现,在使用Gradle时,我们并没有像上面的parent.configChild()一样指明方法调用的对象,而是在build.gradle文件中直接调用task(),apply()和configuration()方法等,这是
因为在没有说明调用对象的情况下,Gradle会自动将调用对象设置成当前Project。比如调用apply()方法和调用project.apply()方法的效果是一样的。查查Gradle的Project文档,你会发现这些方法都是Project类的方法。
 
另外举个例子,对于configurations()方法(它的作用我们将在后面的文章中讲到),该方法实际上会将所跟闭包的delegate设置成ConfigurationContainer,然后在该ConfigurationContainer上执行闭包中的代码。再比如,dependencies()方法,该方法会将所跟闭包的delegate设置成DependencyHandler。
 
还有,Project还定义了configure(Object object,Closure configureClosure)方法,该方法是专门用来配置对象的(比如Task),它会将configureClosure的delegate设置成object,之后configureClosure中的执行代码其实是在object上执行的。和Groovy Bean一样,delegate机制的一个好处是可以增加所创建DSL的可读性。

时间: 2024-09-17 04:02:27

Gradle学习之基本语法入门的相关文章

Gradle学习之第一步入门操作

请通过以下方式下载本系列文章的Github示例代码: git clone https://github.com/davenkin/gradle-learning.git     和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作用的是Task和Plugin.Gradle在默认情况下为我们提供了许多常用的Plugin,其中包括有构建Java项目的Plugin,还有War,Ear等.与Maven不同的是,Gradle不提供内建的项目生命周期管理,只是java Plugin向Proj

学习网页制作基础入门教程(8)框架标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 学习网页制作基础入门教程(5)图象标签 学习网页制作基础入门教程(6)连接标签 学习网页制作基础入门教程(7)表格标签 框架概念 1. 首先,各位先看看右边这张图片,将利用这张图来做解释,这样子,讲起来可能会清楚一些. 我们可以看见,右边的这个图片,一共分为 1 . 2 . 3 三个框架,每一个框架,各有

学习网页制作基础入门教程(3)字体标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 标题标签 1. 使用方法:<H1>标题內容</H1> 2. 标签解释:标题的大小一共有六种,两个标签一组,也就是从 <H1> 到 <H6> , <H1> 最大,<H6>最小.使用标题标签时,该标签会将字体变为粗体字,并会自成一行. 3. 使用范例: 原始碼 呈現結果 <H1>标题1</H1> 标题1

学习网页制作基础入门教程

教程|入门教程|网页 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 学习网页制作基础入门教程(5)背景标签 学习网页制作基础入门教程(6)连接标签 学习网页制作基础入门教程(7)表格标签 学习网页制作基础入门教程(8)框架标签 学习网页制作基础入门教程(9)序列标签 学习网页制作基础入门教程(10)表单标签 学习网页制作基础入门教程(11)注意的问题

学习网页制作基础入门教程(9)序列标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 学习网页制作基础入门教程(5)图象标签 学习网页制作基础入门教程(6)连接标签 学习网页制作基础入门教程(7)表格标签 学习网页制作基础入门教程(8)框架标签 无序标签 1. 序列标签基本上可分为两种,一种是"无序条列",一种是"有序条列".所谓"无序条列"

学习网页制作基础入门教程(7)表格标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 学习网页制作基础入门教程(5)图象标签 学习网页制作基础入门教程(6)连接标签 表格单元格对齐位置设定 1. 首先我们来看一个最简单的表格: 原始代码 显示结果 <TABLE BORDER=1><TR><TD>1</TD></TR></TABLE&g

学习网页制作基础入门教程(6)连接标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 学习网页制作基础入门教程(5)图象标签 网页内部的连接 1. 使用方法: 先在欲连接处作记号:<A NAME="here"> 这里是你想连接的点 </A> 设定连接:<A HREF="#here"> 连接 </A> 2. 标签解

学习网页制作基础入门教程(5)背景标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 学习网页制作基础入门教程(4)图象标签 背景标签 1. 使用方法:<BODY BGCOLOR="#ffffff" BACKGROUND="bg.jpg"> 2. 标签解释:这个标签其实应该老早就要讲了,毕竟它是制作网页不可或缺的基本要素之一,我们背景颜色或图片的设定以及连接字体的颜色,统统都放在 <

学习网页制作基础入门教程(4)图象标签

教程|入门教程|网页 相关文章: 学习网页制作基础入门教程(1)网页编写 学习网页制作基础入门教程(2)排版标签 学习网页制作基础入门教程(3)字体标签 图象标签 1. 使用方法:<IMG SRC="/UploadPic/2007-7/200777152731585.gif" ALT="本站特约模特儿" ALIGN=RIGHT BORDER=0 HSPACE=2 VSPACE=2 HEIGHT=56 WIDTH=32> 2. 标签解释:目前常见的网页图形