简述:大家知道在java语言中,有三大构建工具,Ant,Maven,Gradle,其中Ant无法管理依赖,我们一个工程,要使用很多第三方不同版本的依赖库,每次打包都需要手动将正确版本放到lib下边,很枯燥且容易出错,正是由于这个原因,Maven如约而至,它弥补了Ant的短板,添加了依赖管理,但随着时间推移,Gradle也逐渐流行起来。下面来为大家一一介绍Gradle为什么比Maven更加强大。
在Maven中,主要功能主要分为5点,分别是依赖管理系统、多模块构建、一致的项目结构、一致的构建模型和插件机制
一、依赖管理系统
-maven为java世界引入了新的依赖管理系统,在pom.xml中以标签组依赖,包括groupId,artifactId以及version标签作为唯一标识进行依赖,代码如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.4</version>
</dependency>
</dependencies>
而Gradle在设计的时候基本沿用了Maven的这套依赖管理体系。不过它在引用依赖时还是进行了一些改进。首先引用依赖方面变得非常简洁,只需要在build.gradle的dependencies代码块中添加一句
implementation 'org.springframework.boot:spring-boot-starter-web:2.5.4'
-Gradle支持动态的版本依赖,将版本号改为+号即为依赖的最新库
-Maven处理依赖库版本不一致冲突很麻烦,而gradle根据Transitive,Force等关键字在配置中很容易就解决了版本不一致问题
二、多模块构建
为了项目高内聚低耦合,Maven和gradle都采用多模块构建模式,在Maven中需要定义个parent POM作为一组module的聚合POM。在该POM中可以使用<modules>标签来定义一组子模块。parent POM不会有什么实际构建产出。而parent POM中的build配置以及依赖配置都会自动继承给子module。
gradle是在根目录的settings.gradle来引入各个modle,暴露给工程,在model目录的build.gradle中添加dependencies代码块中来添加依赖
settings.gradle代码
rootProject.name = 'web-test-demo'
include 'web-test-service'
include 'web-test-base'
build.gradle代码
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlin:kotlin-reflect:1.1.0"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
implementation 'org.springframework.boot:spring-boot-starter-web:+'
implementation project(path: ':library-basic')
implementation project(path: ':web-test-service')
}
三、依赖管理系统
在Ant时代大家创建Java项目目录时比较随意,然后通过Ant配置指定哪些属于source,那些属于testSource等。而Maven在设计之初的理念就是Conversion over configuration(约定大于配置)。其制定了一套项目目录结构作为标准的Java项目结构。一个典型的Maven项目结构如下:
Gradle也沿用了这一标准的目录结构。如果你在Gradle项目中使用了标准的Maven项目结构的话,那么在Gradle中也无需进行多余的配置,只需在文件中包含apply plugin:'java'
,系统会自动识别source、resource、test source、 test resource等相应资源。不过Gradle作为JVM上的构建工具,也同时支持groovy、scala等源代码的构建,甚至支持Java、groovy、scala语言的混合构建。虽然Maven通过一些插件比如maven-scala-plugin也能达到相同目的,但配置方面显然Gradle要更优雅一些。
四、一致的构建模型
Maven的构建周期如下
<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上。而现在项目的构建过程变得越来越复杂,而且多样化,显然Maven对这种复杂度缺少足够的应变能力。比如你想在项目构建过程中进行一项压缩所有javascript的任务,那么就要绑定到Maven的现有的某个phase上,而显然貌似放在哪个phase都不太合适。而且这些phase都是串行的,整个执行下来是一条线,这也限制了Maven的构建效率。而Gradle在构建模型上则非常灵活。在Gradle里可以轻松创建一个task,并随时通过depends语法建立与已有task的依赖关系。甚至对于Java项目的构建来说,Gradle是通过名为java的插件来包含了一个对Java项目的构建周期,这等于Gradle本身直接与项目构建周期是解耦的。
五、插件机制
Maven和Gradle设计时都是插件机制。Maven是基于XML进行配置。所以其配置语法太受限于XML。即使实现很小的功能都需要设计一个插件,建立其与XML配置的关联。比如想在Maven中执行一条shell命令,其配置如下
<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只需要创建一个task任务
task dropDB(type: Exec) {commandLine ‘curl’,’-s’,’s’,’-x’,’DELETE’,"http://${db.server}:{db.port}/db_name"
}
总结:在依赖管理的配置方面,Gradle 采用了Groovy语言来描述,而非传统的XML。XML的好处是语言严谨,这也是为什么在Web服务中采用XML来作为信息交换的格式。但这同样也带来了一一个弊端,那就是灵活度不够。而Groovy本身是-一门编程语言,所以在灵活性方面更胜一筹。这些其实不算啥,都可以实现功能,但编译最重要的还是性能,Spring Boot 官方也给出了数据,一次完整的 Maven 项目构建一般需要一个小时或者以上,而在过去的 4 周时间内,使用 Gradle 构建的平均时间只用了 9 分 22 秒,所以在spring boot源码2.3版本以后都采用了gradle构建