浅谈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.8targetCompatibility = 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,如果文章有什么错误的地方,也欢迎大家指出,一起学习交流。
相关文章:

浅谈Gradle构建工具
一、序言 常见的项目构建工具有Ant、Maven、Gradle,以往项目常见采用Maven进构建,但随着技术的发展,越来越多的项目采用Gradle进行构建,例如 Spring-boot。Gradle站在了Ant和Maven构建工具的肩膀上,使用强大的表达式语…...

如何获取和制作免费的icon图标素材
icon 图标在界面设计中虽然占比不大,但却是不可缺少的设计元素之一。设计师通过 icon 图标,将抽象的概念通俗化,降低用户理解某个操作的难度。而设计师也会通过改变 icon 图标的样式来展现整体界面的视觉效果。icon 图标的风格有很多…...

【MySQL】MySQL索引--聚簇索引和非聚簇索引的区别
文章目录 前言1.聚簇索引和非聚簇索引的概念2.两者详细介绍2.1 聚簇索引2.2 非聚簇索引 3. 两者的区别3.1 数据存储方式3.2 二级索引查询 前言 1.聚簇索引和非聚簇索引的概念 数据库表的索引从数据存储方式上可以分为聚簇索引和非聚簇索引两种。“聚簇”的意思是数据行被按照…...
如何使用 SVG.js 中的一些相关方法来创建、设置和操作 image 元素
SVG.js 是一个基于 JavaScript 的 SVG 库,提供了许多常用的 SVG 元素和方法,方便开发者进行 SVG 图形的创建和操作。其中,image 元素是 SVG.js 中较为常用的元素之一,本文将详细介绍 SVG.js 中与 image 元素相关的方法。 一、创建…...

展会进行时!5月16-18日箱讯与您相约中国航交会
宁波国际会展中心7、8号馆 第五届中国(宁波)国际航运物流交易会 暨2023全球物流企业合作博览会 火爆进行中 箱讯与您相约 8号馆 C033K-C036展位 期待您的光临! 2023年5月16-18日,第五届中国(宁波)国际…...

CMake:递归检查并拷贝所有需要的DLL文件
文章目录 1. 目的2. 设计整体思路多层依赖的处理获取 DLL 所在目录探测剩余的 DLL 文件 3. 代码实现判断 stack 是否为空判断 stack 是否为空获取所有 target检测并拷贝 DLL 4. 使用 1. 目的 在基于 CMake 构建的 C/C 工程中,拷贝当前工程需要的每个DLL文件到 Visu…...
python常见问题及解决方案
Python是一种高级编程语言,具有易于学习、易于阅读和易于维护的特点。然而,即使是最有经验的Python开发人员也可能会遇到一些常见的错误。在本文中,我们将讨论一些常见的Python运行时错误,并提供解决这些错误的办法。 语法错误 …...
JUC之Synchronized与Lock
Synchronized 称之为”同步锁 作用: 保证在同一时刻, 被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果 用法: 1.修饰方法:方法锁,锁的对象是当前对象 2.修饰静态方法:类锁…...
动态规划理论基础
文章目录 定义动态规划与分治问题的区别两种方式实现动态规划方法一:带备忘录的自顶向下法方法二:自底向上法 本质核心解题步骤常见题型划分 定义 动态规划方法通常用来求解最优化问题(optimization problem)。这类问题可以有很多可行解,每个…...

Redis的数据类型
参考文档:https://www.runoob.com/redis/redis-tutorial.html redis当中一共支持五种数据类型,分别是: string字符串 list列表 set集合 hash表 zset有序集合 1、对字符串string的操作 下表列出了常用的 redis 字符串命令 1 设置值 获取…...

vue3鼠标经过显示按钮
在前端开发中,我们经常需要在页面中添加一些交互效果来提升用户体验。其中一个常见的需求就是鼠标经过某个元素时显示一个按钮,这个按钮可以用于触发一些操作或者显示更多的内容。 在本篇文章中,我将会介绍如何使用 Vue3 实现一个鼠标经过显…...
【2023华为OD笔试必会25题--C语言版】《18 最短木板长度》——数组
本专栏收录了华为OD 2022 Q4和2023Q1笔试题目,100分类别中的出现频率最高(至少出现100次)的25道,每篇文章包括原始题目 和 我亲自编写并在Visual Studio中运行成功的C语言代码。 仅供参考、启发使用,切不可照搬、照抄,查重倒是可以过,但后面的技术面试还是会暴露的。✨✨…...
yolov5车道线检测+测距(碰撞检测)
yolov5车道线检测+测距(碰撞检测) 1. 车道线检测2. 测距2.1 测距原理2.2 相机标定2.2.1:标定方法12.2.2:标定方法23. 相机测距3.1 测距添加3.2 主代码4. 实验结果相关链接 1. 基于yolov5的车道线检测及安卓部署 2. YOLOv5+单目测距(python) 3. 具体实现效果...
微服务学习笔记--(Gateway网关)
统一网关Gateway 为什么需要网关gateway快速入门断言工厂过滤器工厂全局过滤器跨域问题 Gateway网关-网关作用介绍 为什么需要网关 网关功能: 身份认证和权限校验服务路由、负载均衡请求限流 网关的技术实现 在SpringCloud中网关的实现包括两种: …...
QML插件的创建及调用
QML插件的创建及调用 创建QML Plugin注册插件调用插件 创建QML Plugin 1、 注册插件 1、可以将qml文件放在qmldir中进行声明。 此种方式需要将qml文件和qmldir放在一起 module EularFrame plugin EularFrameEButton 1.0 MyButton.qml2、可以在*plugin.cpp注册 此种方式只需…...

数据结构学习分享之树的介绍
💓博主CSDN主页:杭电码农-NEO💓 ⏩专栏分类:数据结构学习分享⏪ 🚚代码仓库:NEO的学习日记🚚 🌹关注我🫵带你了解更多数据结构的知识 🔝🔝 数据结构第六课 1. 前言&a…...

MySQL数据库基础2
文章目录 数据类型表的约束 数据类型 1、数值类型:BIT、TINYINT、BOOL、SMALLINT、INT、BIGINT、FLOAT[(M,D)]、DOUBLE[(M,D)]、DECIMAL[(M,D)] FLOAT[(M,D)]:占用四个字节,M表示显示位数,D表示小数位数,精度保证&am…...

AutoSAR PNC和ComM
文章目录 PNC和ComMPNC管理NM PDU结构及PNC信息位置如何理解节点关联PNCPNC状态管理 ComM 通道状态管理 PNC和ComM PNC 和 ComM层的Channel不是一个概念,ComM的Channel对应具体的物理总线数。 在ComM模块中,一个Channel可以对应一个PNC,也可…...
Android studio Camera2实现的详细流程
流程 一、获取CameraManager实例二、获取可用的相机列表三、选择一个相机并打开它四、创建一个CaptureRequest.Builder对象五、设置CaptureRequest.Builder对象的参数六、创建一个CaptureSession对象七、开始预览 代码示例 一、获取CameraManager实例 CameraManager manager (…...

阿里云数据库ClickHouse产品和技术解读
摘要:社区ClickHouse的单机引擎性能十分惊艳,但是部署运维ClickHouse集群,以及troubleshoot都不是很好上手。本次分享阿里云数据库ClickHouse产品能力和特性,包含同步MySQL库、ODPS库、本地盘及多盘性价比实例以及自建集群上云的迁…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...