浅谈Gradle构建工具

一、序言

常见的项目构建工具有Ant、Maven、Gradle,以往项目常见采用Maven进构建,但随着技术的发展,越来越多的项目采用Gradle进行构建,例如 Spring-boot。Gradle站在了Ant和Maven构建工具的肩膀上,使用强大的表达式语言Groovy或者Kotlin使其具有易用、灵活的方式自定义构建逻辑,方便扩展,更加适合大型项目构建。

二、性能对比

相比Maven,Gradle为了提高构建的效率,提出了增量构建的概念。Gradle中是以 task 为单位,将一个task分input、任务本身和output。例如下图:input是jdk版本和源文件,output是变异后的class文件。构建的原理就是监听input的变化,当input发生变化的时候,Gradle才会重新构建,否则认为可以复用之前的构建结果。
在这里插入图片描述
Gradle可以重用同样的input作为缓存,相比增量编译,缓存则可以跨机器共享,当构建的时候,可以直接从CI服务器拉取构建结果,非常方便。除此之外,Gradle还会开启一个守护进程来处理跟各个build任务的交互,所以不需要每次构建都初始化组件和服务。守护进程默认是开启的,可以通过gradle –status查看运行的守护进程。
在这里插入图片描述
这是Gradle和Maven分别构建Apache Commons Lang3耗时的对比,可以看到Gradle的性能提升是很明显的。
在这里插入图片描述

二、构建生命周期

Gradle构建的生命周期可以简单划分为初始化、配置和执行,在生命周期各个阶段都提供了用于回调的钩子函数,方便我们监听整个构建过程。
在这里插入图片描述
上图是简单的钩子函数示例,依赖钩子函数就可以监听构建的过程

// Setting 项目编译前调用
gradle.beforeProject {
    // 在这里写明显无用
    println("gradle.beforeProject...")
}

// 所有项目脚本执行完后调用
gradle.buildFinished {
    println("gradle.buildFinished ...")
}

除了上面的钩子函数,Gradle也包含其他的钩子函数,比如 settingsEvaluated、projectsEvaluated等,网上资料挺多,这里就不再赘述。

三、依赖管理

Gradle也是依赖Maven的仓库用于Jar包的管理,同样也有本地仓库和中央仓库,也可以配置私服,这一点跟Maven的同样的概念的。举个栗子,下面的代码就指定了对应的本地仓库、中央仓库和私服。

buildscript {
    repositories {
        mavenLocal()
        maven {
            credentials {
                // 认证信息 配置私服的用户名和密码
            }
            url = 'https://nexus.xxx.cn/repository/public/'
        }
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.3.RELEASE")
    }
}

Gradle会按照配置顺序进行依赖包的加载和扫描,依赖包通过dependencies定义,跟Maven类似,同样需要指定包名和版本号来定位。

dependencies {
    testImplementation("org.springframework.boot:spring-boot-starter-test:2.1.3.RELEASE")
    api("org.springframework.boot:spring-boot-starter-amqp:2.1.3.RELEASE")
    api 'com.google.cloud:google-cloud-storage:2.4.0'
    annotationProcessor "org.projectlombok:lombok:1.18.24"
}

在dependencies中,包含多种类型指定项目依赖项,整体如下:

类型含义
implementation依赖项是会在编译和运行时使用,不会传递给依赖于你的项目的其他模块
api依赖项是项目的公共 API 依赖项,会在编译、运行和其他依赖于你的项目的模块的编译时使用;如果你的模块是一个库模块,希望这些依赖项对外可见,那么可以使用该关键字
compileOnly依赖项仅在编译时使用,不会被打包到最终的构建产物中
runtimeOnly依赖项仅在编译时使用,不会被打包到最终的构建产物中
testImplementation依赖项仅在测试编译和执行测试时使用,不会传递给项目的主要编译路径
testCompileOnly类似于 compileOnly,但仅适用于测试编译路径
testRuntimeOnly类似于 runtimeOnly,但仅适用于测试运行路径
annotationProcessor依赖项是用于编译时注解处理的依赖项,例如lombok的依赖项

四、依赖版本冲突

在项目实际的构建过程中经常依赖包版本冲突的问题,Maven中可以通过 exclude 的方式移除冲突的包,Gradle其实也类似。遇到依赖包冲突,首先是查看依赖报告,可以排除传递性依赖或者强制指定一个版本。

通过exclude排除传递性依赖

dependencies {
    implementation('com.example:library') {
        exclude group: 'org.unwanted', module: 'unwanted-module'
    }
}

使用force强制指定一个版本

dependencies {
    resolutionStrategy {
        force 'com.example:library:1.0.0'
    }
}

如果强制指定了两个相同的包,只是版本不一样,具体选择哪个版本取决于 Gradle 解析依赖的规则,默认情况下会选择最高版本进行解析。

五、多项目构建

在实际开发过程中,通常都是多个模块进行构建,类似Maven提供Parent的方式用来传递模块依赖关系,Gradle也同样提供了多项目构建的方法,用于统一配置公共属性和依赖。

allprojects {
    apply plugin: 'java-library'
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'maven-publish'

    // JVM 版本号要求
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

allprojects 中用来声明所有子模块的通用配置,能在 build.gradle 中配置的语法也都可以同样在allprojects中编写。

另外,Gradle提供 gradle.properties 文件用来统一声明版本号,类似Maven的 properties标签,方便依赖包版本的统一管理。

举个栗子:

springBootVersion=2.1.3.RELEASE
springBootGradlePluginVersion=2.1.3.RELEASE

声明了依赖包SpringBoot和对应Gradle插件的版本,那么依赖配置项则可以修改为如下

dependencies {
    testImplementation("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")
    api("org.springframework.boot:spring-boot-starter-amqp:${springBootVersion}")
}

六、自动化测试

想要实现Gradle的自动化测试,需要配置测试依赖项,比如这里引入junit4作为测试。

dependencies {
    testImplementation 'junit:junit:4.12'
}

编写相应的测试用例,用 @Test 注解来标记测试方法。Gradle提供了内置的测试任务,使用 gradle test 命令可以方便地运行测试用例并生成测试报告,包括测试结果和覆盖率等信息,提供 HTML 可视化图表,测试报告通常位于build/reports/tests目录下。所以可以将其集成到CI流程中,每次代码提交或构建的时候就能生成相应的报告,还是很直观的。

七、总结

除了上面的内容,Gradle还有很多个性化的用法,比如自定义task等操作来控制构建的流程。因为我之前一直用的都是Maven工具,本身也是Gradle的初学者,最近也是因为新项目而接触Gradle,如果文章有什么错误的地方,也欢迎大家指出,一起学习交流。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自平衡Azure

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值