前言
groovy 不温不火地发展好多年了,为何不能大行其道?
要不是因为Android构建,SpringBoot构建,估计一辈子也不会学习groovy。
gradle我也用了很长时间了,但一直没有深究。
终于有一天,我遇到一个简单的打包需求,不得不坐下来好好学习了一把gradle。
问题
如何在一个springboot项目的build.gradle中写两个task,一个打包fat jar,一个打包thin jar,通过参数来控制。我想当然地认为我只要在两个task中分别配置一下bootJar这个东西就行,但发现情况不简单。
Gradle基本概念
- 项目(Project): 类似一个容器,里面是task和扩展的集合
- 任务(Task):一个可以被执行的实例,Task Type的实例
- 插件(Plugin):一个可以提供Task Type的单元
- 扩展对象(Extension Object):可以被配置的对象
Gradle常见技法
给gradle脚本传参
./gradlew executeTaskTwiceWithParameters -DpropertyValues=value1,value2
task doSomething {
doLast {
println System.getProperty("property")
}
}
控制task的执行顺序
回到本文开始提到的问题。其实,理解了task的配置,执行就比较容易实现了。
task的doFirst, doLast分别在执行之前和之后执行,而task中配置部分是不管你输入啥gradle命令都会执行的。
task taskA {
println "这是配置部分,总会执行"
doFirst {
println "这是执行部分,在task执行之前执行"
}
doLast {
println "这是执行部分,在task执行之后执行"
}
}
然后我们看下面的例子:
interface MyExtension {
Property<String> getMessage()
Property<String> getUser()
}
def extension = project.extensions.create('myconfig', MyExtension)
myconfig {
message = "haha"
user = "kuku"
}
task taskConfig {
doFirst {
myconfig {
message = "hoho"
user = "coolcool"
}
}
}
task taskA {
doLast {
println "${extension.message.get()} from ${extension.user.get()}"
}
}
如果你执行命令:
gradle -q taskA
则输出:haha from kuku
如果你执行:
gradle -q taskConfig taskA
则输出:hoho from coolcool
也就是通过控制任务的执行顺序,来实现不同配置的执行。
元编程
元编程(Metaprogramming)是编写、操纵程序的程序,简而言之即为用代码生成代码。元编程是一种编程范式,在传统的编程范式中,程序运行是动态的,但程序本身是静态的。在元编程中,两者都是动态的[1]。元编程将程序作为数据来对待,从而赋予了编程语言更加强大的表达能力。
编写元程序的语言称之为元语言,被操纵的语言称之为目标语言。根据元语言和目标语言是否相同,我们可以将元编程分为两类:
当元语言即目标语言本身时,元编程是目标语言所支持的高级特性,是在编译期或运行期生成或改变代码的一种编程形式,是狭义上的元编程;当元语言并非目标语言时,元编程侧重代码内容的生成,并不关注目标语言代码的编译和执行,也可以称之为产生式编程(Generative Programming)或者代码生成技术(Code Generation)。我们按照从易到难的顺序来依次介绍这些技术。
什么是DSL
领域定义语言(Domain Specific Language )相关概念:
- 针对的是某一特定类型的问题,
- 语法聚焦于指定的领域问题,
- DSL的应用领域和能力都是非常有限的。
- 其基本思想是“求专不求全”
图灵机
图灵机(英语:Turing machine),又称确定型图灵机,是英国数学家艾伦·图灵于1936年提出的一种抽象计算模型,其更抽象的意义为一种数学逻辑机,可以看作等价于任何有限逻辑数学过程的终极强大逻辑机器。
图灵完备
图灵完备是对计算能力的描述。一门语言为什么要图灵完备呢?可以这么理解:一台计算机也是一个图灵机,一个图灵完备的语言意味着这个语言可以使用计算机完成任何计算机可以完成的任务,也就能够发挥计算机的所有能力。(这句话有点绕口)反之,一个图灵不完备的语言,就意味着不能发挥计算机的所有能力。
大部分编程语言是图灵完备的,但C/C++的宏是图灵完备的吗?
Groovy与DSL
Groovy的很多核心功能对创建内部的DSL很有帮助:
- 动态类型和可选类型
- 动态加载、操纵、执行脚本的灵活性
- 分类和ExpandoMetaClass
- 闭包为执行提供了很好的上下文
- 操纵符重载有助于自由的定义操作符
- 生成器支持
- 灵活的括号(使用一定技巧可以避免括号)
Groovy与DSL的内容主要包括:
- 使用命令链式改进流畅性
- 闭包与DSL(即闭包的delegate)
- 方法拦截与DSL
- 括号的限制与变通的方案
- 分类与DSL
- ExpandoMetaClass与DSL