Skip to content

Latest commit

 

History

History
454 lines (307 loc) · 8.33 KB

Gradle.md

File metadata and controls

454 lines (307 loc) · 8.33 KB

Gradle深入理解

gradle 使用

plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

bootJar {
    enabled = true
}

group = 'com.yinhai'
version = '1.0-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
  	mavenLocal()
    mavenCentral()
}

dependencies {

    implementation 'cn.hutool:hutool-all:5.5.8'
    implementation 'com.alibaba:druid-spring-boot-starter:1.1.23'
    implementation 'org.apache.commons:commons-lang3:3.10'
    implementation 'org.apache.httpcomponents:httpclient:4.5.13'
    implementation group: 'com.alibaba', name: 'fastjson', version: '1.2.75'

    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()

    doFirst {
        jvmArgs "-XX:MetaspaceSize=128m", "-XX:MaxMetaspaceSize=128m", "-Xms1500m", "-Xmx1500m", "-Xmn700m"
    }
}

1. Gradle基础

1.1 Distribution

1.2 Wrapper

./gradlew help

./gradlew build.gradle

# 1. 如果没有对应版本gradle,那么首先下载gradlew版本
# 2. 启动client jvm 查找daemon
# 3. 如果没有daemon运行,那么会先启动daemon jvm
# 4. client发送参数,daemon执行构建,返回日志 

1.3 GradleUserHome

# 默认路径
~/.gradle/

# 保存jar包和其它信息,gradle会定期清理
~/.gradle/caches

# 可以配置全局替换仓库等
~/.gradle/init.d/
~/.gradle/init.gradle

# 所有下载的wrapper
~/.gradle/wrapper

1.4 Daemon

gradle 首先启动一个 client jvm,与后台daemon jvm通讯

client只负责转发请求,传递参数,接受日志

daemon默认3个小时后退出

--no-daemon 不启用gradle daemon

2. Groovy基础

https://github.com/Timesless/groovy-all

2.1 动态调用与MOP

2.2 闭包

// 闭包可以引用外部类的变量,这与lambda不同
def str = "hello"
def c4 = {
  println("$str $it")
/*
    闭包会修改引用的外部变量
    我认为是单线程的缘故,C++ lambda引用外部变量修改的是作为匿名类实例的字段,但不能改外部变量本身,Java则是final捕获的
    Golang闭包修改的也是引用的外部变量作为匿名函数实例的字段的值,外部变量本身的值是不能修改的
    js 和 groovy的闭包则可以修改外部变量本身的值,这应该是单线程的原因
    闭包大约在2003年
*/
  str = "zzz"
}
c4.call("param")
println("==== outer str = " + str)

3 Gradle构建

3.0 Gradle生命周期

我们通常只关心2个阶段

  • configure
  • execution
  1. Initialization

读取项目信息(settings.gradle),决定哪些项目参与构建,为每个需要构建的项目创建Project instance

Project Instance是gradle构建的核心

  1. Configuration(不执行构建,只配置)

对Project实例,运行build.gradle(从头到尾解释执行,本质是grovvy脚本)

  1. Execution

执行配置阶段生成的task

// 定义一个task
task('hello gradle', {
  println('configure')
  
  doLast({
    println('executing task')
  })
})

// 执行结果
configure
executing task

/*
 * 解释:
 *	2. configuration阶段『解释执行build.gradle文件(groovy脚本)』
 *	3. excution阶段 
 *
 *  创建了一个hello gradle的任务,使用闭包「闭包是函数实例」去configure这个task
 */

3.1 Gradle核心模型

// 每个Task由闭包configure
// task(String, Closure)
task("hello gradle") {
    println("configureing ")
    // Configure时,只是将该闭包添加到任务的动作列表的最前面,并不实际执行
    doFirst {
        println('Executing first')
    }
    doLast {
        println('Executing last')
    }
}

3.2 Project API

每一个参与构建的项目对应一个Project实例「与build.gradle构建脚本是一对一的关系」

Project 是一系列 Task的集合

每个Task由闭包configure

// 管理configurations
ConfigurationContainer getConfigurations()
// 管理dependencies
DependencyHandler getDependencies()
// 管理artifacts
ArtifactHandler getArtifacts()
// 管理repositories
RepositoryHandler getRepositories()

3.3 Task API

help任务是所有gradle项目存在的一个任务

task是gradle构建的最小单元,maven中最小单元是每一个lifecycle

  • 编译类
  • 运行单元测试
  • 压缩WAR文件
  • ...
// 定义4个任务
// gradle task2
// gradlew task2
(0..<5).each { i ->
    task('task' + i) {
        // 偶数任务依赖 hello gradle 任务
        if ((i & 1) == 0) {
            dependsOn('hello gradle')
        }
        def captureI = i
        doLast {
            println("Excuting task" + captureI)
        }
    }
}

3.4 Lifecycle与Hook

/*
    钩子函数
    任何无主的函数,gradle都在Project api中查找

    解释执行完build.gradle触发afterEvaluate hook
 */
afterEvaluate {
    println('----- after evaluate -----')
}

4. 插件编写

4.1 构建逻辑的复用

4.2 简单插件

build.gradle

// 使用已定义好的插件
apply plugin: 'java'
apply plugin: 'groovy'
/*
 * apply(Map<String, ?>)
 * apply([plugin: 'java'])
 * groovy 语法糖可省略map的[] -> apply(plugin: 'java')
 * 不产生歧义的情况下可省略() -> apply plugin: 'java'
 */

4.3 script插件

build.gradle

/*
    gradle插件编写

    1. build.gradle class MyPlugin implements Plugin<Project> {}
    2. user.dir/buildSrc/src/main/java/MyPlugin2 implements <Project> {}

    apply plugin: MyPlugin
    apply plugin: MyPlugin2
 */
class MyPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        (5..<10).each { i ->
            project.task('task' + i) {
                println('....plugin task' + i +' configure....')
                // 闭包的延迟执行需捕获外部变量
                def captureI = i
                doLast {
                    println("Excuting task" + captureI)
                }
            }
        }
    }
}

/*
    语法糖 apply plugin: MyPlugin
    desugar,本质等价于
    apply([plugin: MyPlugin])

    当参数是map时,可以省略[]
    当不产生歧义时,方法调用的()可以省略
 */
apply plugin: MyPlugin
apply plugin: MyPlugin2

4.4 buildSrc插件

user.dir/buildSrc/src/main/java/MyPlugin.java

import org.gradle.api.Plugin;
import org.gradle.api.Project;
/**
 * @author yangzl
 * @date 2021/2/8
 * @desc
 *
 * 		gradle 插件抽取到 Java类
 * 		该类不需要声明packeage
 *
 * 	gradle整个过程是如何实现的呢?
 * 	该过程类似于maven的install 本地仓库
 * 		1. 通过约定在buildSrc
 * 		2. 在外层build.gradle运行之前先编译buildSrc
 * 		3. 将buildSrc打包的结果libs下,放入buildScript 下 dependencies { classpath 中 },见build.gradle
 *
 */
public class MyPlugin2 implements Plugin<Project> {

	@Override
	public void apply(Project project) {
		for (int i = 10; i < 15; i++) {
			System.out.println("**** java plugin" + i + " configure ****");
			project.task("task" + i);
		}
	}
}

4.5 发布的插件

binary插件

将项目独立,发布到仓库,在buildScript {} 中引入

==apply plugin: 'java'是将插件引入到buildScript{}中,供configure阶段使用==

5. 实际插件分析

6. 构建聚合项目

// parent -> build.gradle
allProjects {
  group 'com.yangzl'
  version: '1.0-SNAPSHOT'

  apply plugin: 'java'

  sourceCompatibility = 1.8

  repositories {
    mavenLocal()
    mavenCentral()
  }

  dependencies {
    compile 'org.spring.framework:spring-context:5.0.2.RELEASE'

    testCompile group: 'junit', name: 'junit', version: '4.12'
  }
}

// service -> build.gradle
dependencies {
  complie project(":dao")
}

// dao -> build.gradle

// web -> build.gradle
apply plugin: 'war'