跟我学Gradle

跟我学Gradle

Scroll Down

先问个问题:你们项目中常用的构建工具是什么?

我猜,大部分小伙伴应该都会不约而同的说:Maven。

说到 Maven ,相信大多数的 Java 开发者一定不会不陌生,当然,有实力的同学可以把精通打在公屏上(简历上)。

但咱们今天的主角并不是它,而是另外一个:Gradle

Gradle 也是一个自动化构建的开源工具,它的构建脚本是基于 Groovy 或者 Kotlin 的特定领域来实现的,而不是我们在 Maven 中使用的 XML。

这时肯定会有小伙伴会问,Maven 不是已经能够满足我们平时的项目构建功能需求了吗,为什么有整一个 Gradle 出来呢?

存在即合理。

我们来看一下 gradle 的几个优势:

  1. 简洁性

    相信不少人都体验过,在一个比较大的项目中,其依赖可能有几十个,而维护的 XML 可能就有上百行,而且每添加一个依赖,至少都要添加三行。而使用 Gradle ,仅需要一行就能实现。依赖配置的大小是其三分之一,而且维护起来更加简洁方便。

  2. 灵活性

    从这一点来看,gradle 的灵活性可谓是甩了 Maven 好几条街。

    在 Maven 中如果你想对构建增加一些自定义的逻辑,大部分情况下需要引用外部的插件,非常麻烦。而对于 Gradle 来说,只需要编写简单的脚本即可使用。当然,前期还是需要一点脚本语言学习的成本,但是一旦你熟悉了,后面想对其任意扩展就轻而易举的事了。

  3. 速度快

    Gradle 使用构建缓存、守护进程等方式提高编译速度。

    Gradle 官网上提供了各场景的测试性能对比:

    比如,将 Apache Commons Lang 3 项目从 Maven 迁移到了 Gradle,测试的结果是:Gradle在运行测试上快了1.7倍,而在开启cache的时候快了30倍!

    又或者是,10个模块的多项目构建的常见任务的结果,类似于微服务的应用工程。每个子项目有50个源文件和50个测试源文件,测试的结果是:Gradle在纯净构建上快2-3倍,而在增量构建上快了7倍,在Gradle任务输出被缓存的情况下可以提升至14倍!

    • 在所有场景下,Gradle 都至少比 Maven 快2倍
    • 当增量构建时,Gradle 比 Maven 快7-85倍,子项目越多,Gradle 快的越多
    • 当 Gradle 的构建缓存可以解析任务输出的时候,Gradle 比 Maven 快 3-30 倍

    上述测试数据来自 Gradle 官方文档

    这也是为什么 Spring Boot 2.3.0.M1 后选择从 Maven 迁移到 Gradle 的原因,因为它实在是太快了。

  4. 兼容性

    支持 maven 和 ant 仓库、支持多个语言,比如 Java、Kotlin、Groovy 等。

Gradle 快速入门

创建一个 Gradle 的工程后,在工程结构上它与 Maven 工程不一样的,主要是在 Maven 配置是在 pom.xml文件 ,而 Gradle 则是在 build.gradle

我们知道在 Maven 的 pom.xml 会定义一些依赖、仓库地址、版本信息等。而在 Gradle 的 build.gradle 其实也是大同小异,只不过是配置的写法会有些稍微不同,可以说是更加简单和简洁。

repositories

Gradle 支持 Maven 和 Ant 的仓库配置。下面贴上使用 Maven 仓库的配置方式,小伙伴们可以根据实际场景自行选择仓库镜像源。

repositories {
    // 中央仓库
    mavenCentral()
    // 腾讯云镜像仓库
    maven { 
      url "http://mirrors.cloud.tencent.com/nexus/repository/maven-public/"
    }
    // 私服配置
    maven {
        name "xxx"
        url "http://nexus.xxx.com"
        credentials {
            username "admin"
            password "admin"
        }
    }
}

dependencies

作为项目管理工具,依赖管理必然是核心模块之一。

ext {
    springBootVersion = "2.3.8.RELEASE"
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
    }
  	dependencies {
   				
    }
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

我们知道在 Maven中 dependencies 依赖是有 scope 的维度区分:

  • compile:默认的依赖范围,在所有的classpath 中可用,同时它们也会被打包。
  • provided:在编译和测试时有效,运行时不会引入。简单说就是非传递依赖。
  • runtime:运行范围,运行和测试环境使用,编译时不用加入classpath,打包时候会加入。
  • test:只有在测试编译和测试运行阶段可用
  • systemt:与provided 类似,但是你必须显式的提供一个对于本地系统中JAR 文件的路径。

当然,Gradle 也提供相对应 scope 的实现,只不过方式有些稍微的区别,我们看一下比较常见的定义:

// 类比 maven 中的 compile,依赖传递
api("org.springframework.boot:spring-boot-starter-web")

// 类比 maven 中的 provided,非依赖传递
implementation("org.springframework.boot:spring-boot-starter-web")

// 在编译时需要,但在运行时不需要的依赖项。
compileOnly ("org.projectlombok:lombok:1.18.18")

// 声明的依赖关系只在运行时需要,而不是在编译时
runtimeOnly

// 注释编译期间使用的处理器。
annotationProcessor "org.projectlombok:lombok:1.18.18"

// 只在测试时依赖,当然还有 testCompileOnly、testRuntimeOnly等等
testImplementation("org.springframework.boot:spring-boot-starter-test")

plugins

没错,这里的 plugins 对应的就是 maven 中的 plugins,不过 gradle 中的 plugins 更加的灵活、便捷。

我们可以直接使用 Gradle插件中心 公共插件,当然也可以通过编写 groovy 自定义插件。

可能有些同学会看到还有通过 apply 的方式,这种是老版本 2.1 之前的用法了。

plugins{
    id 'java'
    id 'org.springframework.boot' version '2.3.8.RELEASE'
}

上面可以看到 java 也是以插件的形式引入的,为什么 maven 中就不用了呢?

这里就需要简单讲一下 Gradle 的一些比较基础的概念。

Task(任务)是 Gradle 其中一个比较核心的概念,每个项目都是由多个 task 组成。比如说一个对于 Java 项目来说,一个项目的整个构建生命周期是包括:编译、打包、发布这几个操作,而每个操作可以理解为代表一个 task。

Gradle 的项目构建生命周期并不是 Gradle 的内建机制,而是由 Plugin 引入的。

在引入 java 插件后,同时也会引入如下的 task

:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build

这里的 task 是不是跟 maven 中构建项目的操作很相似呢~

构建上传&发布

对于要把 jar 包发布到私服仓库的需求,我们可以借助 maven-publish 插件轻松实现。

plugins{
    id 'java'
    id 'maven-publish'
}

publishing {
  
  publications {
    maven(MavenPublication) {
      from components.java
    }
  }
  // 设置仓库地址
  repositories {
    maven {
      name "maven-release"
      url ""
      credentials {
        username "admin"
        password "admin"
      }
    }
    maven {
      name "maven-snapshot"
      url ""
      credentials {
        username "admin"
        password "admin"
      }
    }
  }
}

依赖检查

我们有时可能需要查看项目的引用依赖或者依赖传递信息,通过 gradle dependencies 查看依赖树。

如果是 maven 我们借助 idea 上的 maven-helper 的来取排查,这样子会更方便一点。

.....

总的来说,Gradle 整体比 Maven 更加灵活和高效,但是学习的成本和操作也会更加高一丢丢。

它更常用在 Android、Kotlin、Groovy 等语言开发的项目中,但是现在像 Spring、Hibernate 等这些开源项目也选择 Gradle 做为项目管理构件工具,足以说明它的一个未来发展趋势。所以说,尽管你可能现在用不上,但是技多不压身嘛。

以上是小年 Gradle 入门学习的一些总结,当然还有更多的学习技巧,后续会陆续分享。

普通的改变,将改变普通

我是宅小年,一个在互联网低调前行的小青年

关注公众号「宅小年」,个人博客 📖 edisonz.cn,阅读更多分享文章