gradle学习笔记

1.gradle是一个项目构建工具,就像7-zip一样,我们可以把它下载到本地拿来使用

2.gradle是用Java语言写成的项目构建工具,就像tomcat一样,tomcat是用Java语言写成的web服务器

3.groovy是一门编程语言,像Java一样,也运行在jvm之上,只不过,jvm运行的大部分应用程序都是由Java编写的。由此可见,JVM已经不仅仅只是Java语言的执行引擎,而是像.net一样,成为了一个运行平台,在其之上,可以运行由很有语言写成的程序,比如Java、groovy、kotlin。由此可知,Java规范用于约束Java语言,JVM规范则用于定义JVM,不是一回事儿。groovy既然运行于JVM之上,那么它也必须服从JVM规范才能运行,也即是,像Java一样,需要编译为字节码文件,然后由JVM执行。

3.gradle内置groovy引擎,它可以通过调用groovy引擎来运行groovy脚本。就像我们可以在Java应用中通过ScriptEngine相关的接口执行Javascript脚本一样。

4.gradle的配置文件build.gradle、setting.gradle都是由groovy语言写成的,gradle通过调用groovy引擎来运行它的这些配置文件,从而实现gradle的功能。

5.groovy引擎只是一个抽象概括。web浏览器运行Javascript需要javascript引擎,在Java中运行javascript也需要javascript引擎,目前在Java中已经内置Nashorn,它就是一个JavaScript引擎。当然这个Nashron与groovy引擎一样,都是通过JVM运行。groovy引擎运行groovy脚本时,包含两个步骤。1.编译。将groovy脚本编译为字节码文件。2.运行。通过JVM运行这个已经编译为字节码文件的脚本。

6.gradle为何使用groovy呢?xml编写配置文件复杂,而通过groovy特有的语法,写出的gradle配置文件相当简单明了。groovy语言的这种特性,也就是DSL。如果把javascript比作groovy,那么json就是groovy的DSL。

7.在命令行中输入gradle --help,查看如何使用gradle。


USAGE: gradle [option...] [task...]

-?, -h, --help            Shows this help message.
-a, --no-rebuild          Do not rebuild project dependencies. [deprecated]
-b, --build-file          Specify the build file.
--build-cache             Enables the Gradle build cache. Gradle will try to reuse outputs from previous builds. [incubating]
-c, --settings-file       Specify the settings file.
--configure-on-demand     Configure necessary projects only. Gradle will attempt to reduce configuration time for large multi-project builds. [incubating]
--console                 Specifies which type of console output to generate. Values are 'plain', 'auto' (default), 'rich' or 'verbose'.
--continue                Continue task execution after a task failure.
-D, --system-prop         Set system property of the JVM (e.g. -Dmyprop=myvalue).
-d, --debug               Log in debug mode (includes normal stacktrace).
--daemon                  Uses the Gradle Daemon to run the build. Starts the Daemon if not running.
--foreground              Starts the Gradle Daemon in the foreground. [incubating]
-g, --gradle-user-home    Specifies the gradle user home directory.
-I, --init-script         Specify an initialization script.
-i, --info                Set log level to info.
--include-build           Include the specified build in the composite. [incubating]
-m, --dry-run             Run the builds with all task actions disabled.
--max-workers             Configure the number of concurrent workers Gradle is allowed to use. [incubating]
--no-build-cache          Disables the Gradle build cache. [incubating]
--no-configure-on-demand  Disables the use of configuration on demand. [incubating]
--no-daemon               Do not use the Gradle daemon to run the build. Useful occasionally if you have configured Gradle to always run with the daemon by default.
--no-parallel             Disables parallel execution to build projects. [incubating]
--no-scan                 Disables the creation of a build scan. For more information about build scans, please visit https://gradle.com/build-scans. [incubating]
--offline                 Execute the build without accessing network resources.
-P, --project-prop        Set project property for the build script (e.g. -Pmyprop=myvalue).
-p, --project-dir         Specifies the start directory for Gradle. Defaults to current directory.
--parallel                Build projects in parallel. Gradle will attempt to determine the optimal number of executor threads to use. [incubating]
--profile                 Profile build execution time and generates a report in the <build_dir>/reports/profile directory.
--project-cache-dir       Specify the project-specific cache directory. Defaults to .gradle in the root project directory.
-q, --quiet               Log errors only.
--recompile-scripts       Force build script recompiling. [deprecated]
--refresh-dependencies    Refresh the state of dependencies.
--rerun-tasks             Ignore previously cached task results.
-S, --full-stacktrace     Print out the full (very verbose) stacktrace for all exceptions.
-s, --stacktrace          Print out the stacktrace for all exceptions.
--scan                    Creates a build scan. Gradle will emit a warning if the build scan plugin has not been applied. (https://gradle.com/build-scans) [incubating]
--status                  Shows status of running and recently stopped Gradle Daemon(s).
--stop                    Stops the Gradle Daemon if it is running.
-t, --continuous          Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change. [incubating]
-u, --no-search-upward    Don't search in parent folders for a settings file.
-v, --version             Print version info.
-w, --warn                Set log level to warn.
gradle的使用方法与其他命令的使用方法无异,我们发现原来gradle很简单,紧跟gradle命令的是它的各个参数,然后是“任务”。

由此可知,譬如gradle help、gradle tasks、gradle build、gradle -q help中的help、tasks、build都是它的任务。-q是它的参数。

原来,gradle也就是不断运行各个任务而已。gradle有哪些任务呢?我们可以调用gradle tasks来查看它有哪些任务。

gradle的内置的这些任务当然无法满足我们的需要,那么我们就需要新增任务。

在build.gradle构建脚本中添加

task hello {

print 'hello world'

}

不要奇怪,这段看起来像是配置的文字其实就是groovy的代码。task是方法,hello和{...}是task方法的两个参数,最后这个参数被称为闭包。

然后,执行gradle hello,就可以运行一个简单的任务了。

8.在项目目录下我们经常看到gradle文件夹和gradlew和gradlew.bat。他们是什么?

以前没有他们的时候,我们需要自己下载gradle软件,才能执行gradle命令。现在只要把他们放在项目文件夹下面,就相当于内置了一个gradle,我们就不用使用项目外的gradle执行task了。显而易见,n个人可能会使用n个版本的gradle来执行task,使用内置的gradle则可以避免这个问题。而且在把含有内置的gradle的项目导入到IDE中时,IDE可以识别出这个项目究竟是使用了哪个版本的gradle,自动使用这个内置的gradle执行任务,完美的解决了兼容性的问题。完整版本的gradle内置到项目中不太现实,因为完整的gradle太大了。于是,这个内置的gradle实际上只是个外壳,他会自动下载完整版本的gradle,然后来运行gradle,运行内置的gradle与外置的gradle本身没有什么区别。这个内置的gradle被称为gradle wrraper,也即是gradle包装器。

9.项目目录下的.gradle文件夹是什么?可以删除吗?

运行一个gradle任务,比较耗时,于是gradle想出了一个点子,在运行一个task任务时,会把必要的一些信息缓存下来,下次再运行任务时,如果有缓存,那么运行起来就比较快了,而不是从头开始、重新运行。这个文件夹就是gradle的项目缓存文件夹。可以删除,可想而知,删除后,它会自动生成,并且在自动生成前执行的gradle任务会很慢。

10.在运行gradle任务时,经常出现gradle deamon。它是什么?

deamon是守护的意思。就是gradle守护进程。原来,gradle在执行任务时,并不是由当前的gradle命令进程执行的,而是把任务委托给了gradle deamon进程,由这个后台进程来执行任务。打开任务管理器,我们可以看到这个gradle后台进程。

11.gradle的生命周期

每个项目都有一个build.gradle(也可以没有),整个构建只有一个settting.gradle(也可以没有)

在执行gradle任务时,gradle首先加载setting.gradle文件,以确定gradle的项目架构。

比如

project1

----------project2

--------------------project21

--------------------project22

----------project3

----------project4

这里总共有6个项目,project1是根项目,project2、project3、project4是它的子项目,project21和project22是project2的子项目

每一个项目都有“项目名”、“项目文件路径”、“项目架构路径”、“项目构建脚本路径”,“项目构建路径”等属性。

project1的项目架构路径是“:”

project2的项目架构路径是“:project2”

project21的项目架构路径是“:project2:project21”

通过项目架构路径可以唯一的确定是哪个项目

架构路径“project2”和“:project2”不同,前者是相对路径,后者是绝对路径

为何需要项目架构路径呢?

项目架构路径不仅用于标识项目,还用于标识任务。

比如执行clean任务时,gradle将检查每一个项目,执行存在clean任务的所有项目的clean。很多项目都执行了clean,怎么知道每个clean分别是哪个项目的?这就要用到项目架构路径。

12.gradle在执行setting.gradle和build.gradle时,不可能是直接将其委托给groovy引擎进行编译执行,猜测,gradle会对setting.gradle和build.gradle进行一定的处理后,再将其委托给groovy引擎进行编译执行。gradle怎么进行的处理呢?

猜测:gradle把setting.gradle的内容放置在了一个类的run方法内,这个类实现了Setting接口。把build.gradle的内容放置在了一个类的run方法内,这个类实现了Project接口,而且这些类还默认import了一些其他类(如Copy、Delete类),然后,gradle将这两个源代码委托给groovy引擎进行编译执行。由此可见,setting.gradle和build.gradle可以类比成JSP文件,setting.gradle中的this对象是Settings实现类的一个对象,build.gradle中的this对象是Project实现类的一个对象。

13.请看如下build.gradle:

task hello (group:"My Tools") {
    print "hello world!"
}

上文说到,上述代码,gradle会把它放置在一个实现Project接口的类的run方法中。

上面这段代码不容易看懂,把它等价转为易懂的groovy代码:

task(hello([group:"My Tools"],{ print "hello world!" })

这段代码,首先调用了hello方法,hello方法有两个参数,第一个是[group:"My Tools"],第二是{ print "hello world!" }。其中,第一个是包含了一个键值对的Map对象,第二个是一个闭包。然后调用了task方法,task方法的参数就是hello方法的返回值。

查询Project类的文档,发现他有三个重载的task方法:

Task task(String name) throws InvalidUserDataException;
Task task(Map<String, ?> args, String name) throws InvalidUserDataException;
Task task(Map<String, ?> args, String name, Closure configureClosure);

显然,实际调用的是第一个task方法,第一个task方法的参数是任务的名称。

那么hello方法的返回值一定是hello方法的方法名。

hello方法虽然没有定义,但groovy支持方法委托。hello方法一定是委托给了代理方法。这个代理方法把方法名返回。把闭包保存了起来。等到run方法执行完毕后,再查询出task,设置task的属性。

从上面,我们还可以看到task有一个重载方法Task task(Map<String, ?> args, String name, Closure configureClosure);

这个重载方法也是支持闭包的。显然,上述对task的定义还可以写成:

task group:"My Tools","hello",{

print hello,world

}

这种写法就是直接调用project接口的task方法了,只不过这种写法不够简洁而已,但是容易理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值