Java世界中主要有三大构建工具:Ant、Maven和Gradle。经过几年的发展,Ant几乎销声匿迹、Maven也日薄西山,而Gradle的发展则如日中天。目前,诸如spring等框架源码的建构工具也都从maven转到gradle上了,说明了掌握gradle是一个必备技能了。

依赖管理

  • 简洁的依赖

    相较于maven的引用依赖,gradle显得更加简单,类似于:

    1
    2
    3
    4
    dependencies {
    compile 'org.hibernate:hibernate-core:3.6.7.Final'
    testCompile ‘junit:junit:4.+'
    }
  • 依赖项的scope

    Maven世界中,一个依赖项有6种scope,分别是complie(默认)、provided、runtime、test、system、import。而grade将其简化为了4种,compile、runtime、testCompile、testRuntime。

    如果想实现其他的效果,需要自己编写代码来实现。

  • 动态版本依赖

    maven如果不填写具体的版本号,会自动使用最新的;gradle在版本号后面使用+号的方式可以实现动态的版本管理。

  • 依赖冲突解决

    解决依赖冲突方面Gradle的实现机制更加明确。使用Maven和Gradle进行依赖管理时都采用的是传递性依赖;而如果多个依赖项指向同一个依赖项的不同版本时就会引起依赖冲突。Gradle在解决依赖冲突方面相对来说比较明确

多模块构建

在maven项目中,一般用<modules>标签定义一组子模块,父模块中的配置和属性会自动继承给子模块。

Gradle中的父模块和子模块可以用allprojectssubprojects模块分别定义。对于子模块的定义放置在setttings.gradle中,比Maven更加灵活。例如下例子,在parent的bulid.gradle中有:

1
2
3
allprojects {
task hello << { task -> println "I'm $task.project.name" }
}

执行这个方法会打印出所有父模块和子模块的项目名。

一致的项目结构

maven的设计思想为约定大于配置,Gradle也沿用了这一标准的目录结构。如果你在Gradle项目中使用了标准的Maven项目结构的话,那么在Gradle中也无需进行多余的配置,只需在文件中包含apply plugin:’java’,系统会自动识别source、resource、test srouce、 test resource等相应资源。

不过Gradle作为JVM上的构建工具,也同时支持groovy、scala等源代码的构建,甚至支持Java、groovy、scala语言的混合构建。虽然Maven通过一些插件(比如maven-scala-plugin)也能达到相同目的,但配置方面显然Gradle要更优雅一些。

一致的构建模型

为了解决Ant中对项目构建活动缺乏标准化的问题,Maven特意设置了标准的项目构建周期,其默认的构建周期如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>

Maven将项目的构建周期限制的太死,你无法在构建周期中添加新的phase,只能将插件绑定到已有的phase上。而且这些phase都是串行的,整个执行下来是一条线,这也限制了Maven的构建效率。

而Gradle在构建模型上则非常灵活。在Gradle世界里可以轻松创建一个task,并随时通过depends语法建立与已有task的依赖关系。甚至对于Java项目的构建来说,Gradle是通过名为java的插件来包含了一个对Java项目的构建周期,这等于Gradle本身直接与项目构建周期是解耦的。

插件机制

Maven和Gradle设计时都采用了插件机制。但显然Gradle更胜一筹。主要原因在于Maven是基于XML进行配置。所以其配置语法太受限于XML。即使实现很小的功能都需要设计一个插件,建立其与XML配置的关联。比如想在Maven中执行一条shell命令,其配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>drop DB => db_name</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>curl</executable>
<arguments>
<argument>-s</argument>
<argument>-S</argument>
<argument>-X</argument>
<argument>DELETE</argument>
<argument>http://${db.server}:${db.port}/db_name</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>

而在Gradle中则一切变得非常简单。

1
2
3
task dropDB(type: Exec) {
commandLine ‘curl’,’-s’,’s’,’-x’,’DELETE’,"http://${db.server}:{db.port}/db_name"
}

以上的五个方面是gradle和maven最主要的优化特性。

参考于https://www.cnblogs.com/lykbk/p/erwerwerwerwerwerwe.html