Maven和Gradle比较

maven

优点

  1. 流程简单而死板,没有魔法
  2. 稳定可靠
  3. 插件众多,用户广泛

    缺点

  4. 不灵活

  5. 要实现一些非常灵活的小需求,很要命
  6. xml配置很啰嗦

gradle

优点

  1. 极端灵活方便
  2. 新颖,空能更多
  3. 对于大项目的性能更好

    缺点

  4. 较为复杂,学习成本高

  5. 演进过于迅速,社区跟不上

核心理念:maven vs gradle

maven

  • 一套定义好的流程,插件在这个流程上绑定工作
  • 所有的配置都通过xml进行

    gradle

  • 一个定义好的软件模型,些groovy/kotlin脚本去配置它

  • 基本的工作单元是任务
  • 所有的配置都通过DSL(Domain specific Language)进行 DSL领域专属语言

Gradle的基本概念

Gradle的distribution

  • 和jvm上绝大多数工具一直,script+libs

    Gradle wrapper(gradlew)

  • 通过一个脚本,需要时下载正确的版本,保证构建的稳定性

    Gradle daemon

  • 通过后台进程保证代码的复用

  • 推荐打开,不要开网上的教程

image.png
daemon是在后台一直运行的守护进程,gradle命令会启动一个小型jvm,和daemon进程进行通信,daemon进程里面会加载类库,在以后用gradle进行构建的时候,可以直接使用daemon进程里面的类库,加快构建的速度。

Groovy基础

groovy就是在java上面写python

Groovy是java的超集

  • 语法糖(声明list map 方法调用。。。)
    • List []
    • Map [:]
    • String “$val”
    • def弱类型

image.png

  • 默认getter/setter

自动生成get set方法
image.png
直接访问属性的花,会自动执行get方法

  • 闭包

Groovy的MOP(元对象协议)

  • 默认一切均为反射,动态调用

image.png

  • 可以静态编译
  • 也可以实现类似eval的功能

函数式与闭包

在2003年,怎么在jvm上进行函数式编程

groovy是jvm上的python
闭包是一等公民,闭包是对象,可以传递
闭包的委托机制,也是DSL的核心,同时影响了Kotilin script
闭包对JDK,尤其是集合框架的增强

Gradle的核心概念

Project

一个build.gradle文件对应一个Project

类比Maven的一个pom对应一个模块

build.gradle

构建脚本

一个以Project对象为delegate的代码片段

Task

构建脚本中定义的最小的工作单元

任务之间可以依赖

可以动态创建

image.png
image.pngimage.png

Gradle的生命周期

三个阶段(注意:不是maven的阶段)

  1. 初始化(initialization)

扫描构建包含的项目 settings.gradle(.kts)

  1. 配置项目(configuration)

从上到下执行构建脚本build.gradle(.kts)

  1. 执行选中的任务(execution)

通过命令行传递要执行的任务列表
image.png
1和2,会在配置的时候被执行。 3只有在确切的要执行任务的时候才会被执行打印 如果命令 gradlew aaa. 那么配置阶段会打印出1 2,任务执行阶段打印出3 但是命令gradlew 只会进行配置,打印3的函数会被存储起来,不被执行,未来指定它执行的时候,他才会被执行

LifeCycle hooks

Project.afterEvaluate {}

脚本执行完的回调函数。执行完最后一行,会执行afterEvaluate函数。
image.png

Gradle:使用Task

构建脚本中定义的最小的工作单元

  • task(“myTask”){}

    任务之间可以依赖

  • taks.dependsOn

B依赖A,所以会先执行A任务,再执行B
image.png
image.png

可以动态创建

  • 100.times{ tasks.create(“task$i”) }

传入参数,动态的创建了任务,任务的个数可以用过命令行,把参数传进去
image.png

访问Task及其属性

  • 配置Task的属性和动态增加逻辑
    • task{}中的代码会立即执行
    • 但是doLast{}中的代码会按需执行
  • 编写和使用可以服用的Task类
    • 使用自带的众多Task实现类
    • 自己编写Task的实现类

image.pngimage.png

任务逻辑的复用
image.png
image.png

Gradle:增量构建

增量构建怎么实现?

  • 为每个任务定义输入和输出
  • 如果输入和输出自上次构建依赖均为改变,则无需重复执行

    使用注解声明增量构建

  • 再getter方法上声明

    使用运行时API动态声明增量构建

检查文件和原先是否一样,如果不一样就执行构建,一样的话,则不执行。
image.png
image.png

Gradle的依赖管理

gradle依赖管理初步

  • Gradle声称100%兼容maven
  • 使用repositories{ }声明仓库
  • 使用dependencies{ }声明依赖
  • 再依赖声明的背后发生了什么?
    • 通过Groovy/Kotlin的动态调用,将这些信息存储起来

image.png
第一行,自动执行了一下的任务。这些插件就自动调用了java的编译的逻辑。
image.png等等等等

自定义Gradle构建

gradle.properties

  • 全局或者项目
  • 所有的命令行参数都可以放在gradle.properties中

    init脚本

  • 全局或者构建参数

    -Pkey=value

  • 直接再构建中使用,参数传递

image.png

再Gradle构件中使用第三方类库

  • buildscript

image.png
指的是这个build.gradle这个脚本本身的,自己要用的依赖包。而下面的则是项目中需要用到的依赖包。
image.png

再Gradle中复用代码逻辑

  • Gradle构建本质上就是构建脚本依次执行
  • 如果我们想要复用一些逻辑呢?
  • 朝见就是狗叫逻辑的打包

    插件

image.png

编写简单的脚本插件

把复用的逻辑,写成一个gradle文件,然后再build.gradle中使用apply fro语句可以引入这段可复用的逻辑
image.png

将逻辑提取给类

image.png

拆分构建逻辑
image.png
image.png