Gradle学习系列之读懂Gradle语法

转载地址:

http://www.cnblogs.com/CloudTeng/p/3418072.html



  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-08-28 09:15:31

Gradle学习系列之读懂Gradle语法的相关文章

Gradle学习系列之一——Gradle快速入门(转)

这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构建多个Project 自定义Task类型 自定义Plugin 请通过以下方式下载本系列文章的Github示例代码: git clone https://github.com/davenkin/gradle-learning.git 和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作

Gradle学习系列之一——Gradle快速入门

Gradle学习系列之一--Gradle快速入门 这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构建多个Project 自定义Task类型 自定义Plugin 请通过以下方式下载本系列文章的Github示例代码: git clone https://github.com/davenkin/gradle-learning.git 和Maven一样,

Gradle学习系列(一)

今天就开始学习Gradle构建了,听说很牛X.本篇内容就带领我初步窥探Gradle的世界. 1.什么是Gradle 相信之前都接触过用Ant或者Meavn进行项目的构建,两者各有千秋,Ant的灵活性,以及Meavn的强大依耐性都让它们在构建的世界里占据了一席之地.然而Ant的复杂配置以及Meavn的不灵活,都让程序猿们头疼万分.于是乎,新一代的构建黑马已悄然出世了,它就是Gradle.让我们欢迎它的到来! 所以Gradle就是新的一种构建工具,只不过它不再使用XML来编写自己的构建脚本了区别了A

Gradle学习系列(三)

上一篇我们已经学习了 Gradle 打包,那么这一节 就开始讲讲本章的第二版块:打包及使用Gradle过程中的常见错误问题. 有时候我们需要编辑一个开源项目之类的,希望把它导入了我们自己的IDE工具中比如AS,那么在导入过程中我们会经常遇到些错误,有时提示 gradle版本不对了或者buildTools工具不对啦或者某个命令用的不对啦等等这些细小问题,这时候去一一修改它了, 1.>提示 gradle版本不对 : 我们就需要去project根目录下的build.gradle里面查看 gradle的

Gradle学习系列(二)

AS的逐渐成熟和完善,已有越来越多的项目开发都开始转向AS了,必然的对Gradel的认识和使用是很有必要了.我们已经知道 Gradle 是用来架构 Java项目了,对于Android Project来说,说白了我们就是用它来打包.因为在这一块,等你接触之后,你就会发现相比较Ant等其它打包工具来说,它是有多么的方便和高效.然而本系列的第一篇已大致的介绍了Gradle的基础知识,本章开始将重点讲讲 用Gradle 打包细节以及使用过程中遇到的一些常见问题和错误.本章主要分为两个板块,第一个版块,主

gradle学习系列之eclipse中简单构建android项目

看不到图片可以去访问这个网址看看:http://pan.baidu.com/s/1o6FrFkA 一.什么是Gradle 官网www.gradle.org上介绍Gradle是升级版(evolved)的自动化构建工具.它可以自动构建,测试,发布,部署,同时使更多的软件包或其他类型诸如生成静态网站,文档等项目自动化. Gradle 将Ant的功能和伸缩性与Maven的依赖管理及约定结合成一种更加高效的方式去完成构建.它采用了Groovy 特定领域语言和诸多创新方法,提供了一种声明式的方式用合理的默认

【坚持】Selenium+Python学习之从读懂代码开始 DAY1

学习Selenium+Python已经好几个月了,但越学发现不懂的东西越多. 感觉最大的问题还是在于基础不扎实,决定从头开始,每天坚持读代码,写代码. 相信量变一定能到质变!!! 2018/05/09 [来源:菜鸟教程](http://www.runoob.com/python3/python3-examples.html) class float([x]) Return a floating point number constructed from a number or string x.

gradle学习之旅(四) 使用gradle构建简单的java web项目

本节通过一个简单的javaweb项目来体会gradle的使用 需求 构建一个javaweb项目,搭建jsp+servlet开发环境 可以将需求分解为两步: 使用gradle构建一个java项目 为该项目构建web视图层 工具 gradle4.3 idea jdk 1.8 实验过程 首先在idea中创建一个空的gradle项目 创建如下目录-文件结构 在构建脚本中写入如下内容 group 'com.shy' version '1.0-SNAPSHOT' apply plugin:'java' ap

三 vue学习三 从读懂一个Vue项目开始

源码地址:     https://github.com/liufeiSAP/vue2-manage 我们的目录结构: 目录/文件 说明 build 这个是我们最终发布的时候会把代码发布在这里,在开发阶段,我们基本不用管. config 配置目录,默认配置没有问题,所以我们也不用管 node_modules 这个目录是存放我们项目开发依赖的一些模块,这里面有很多很多内容,不过高兴的是,我们也不用管 src 我们的开发目录,基本上绝大多数工作都是在这里开展的 static 资源目录,我们可以把一些