gradle概览
- Distribution
作用 | |
---|---|
src | 源码打包,不能运行 |
bin | 可执行binary脚本(linux/windows) |
all | 除了源码,还有demo |
- 一般通过wrapper
-
Wrapper
- 作用:开发时,保持版本一致;在未安装gradle的机器上执行,
gradle wrapper
时,会启动一个小的jvm加载生成的指令生成的jar包,从gradle官网下载项目对应的gradle版本, - 绑定gradle版本
gradle+版本号 wrapper
gradle wrapper + 项目
指令执行后,会查看本地是否有项目对应的gradle版本,没有则会先去下载到GradleUserHome中去,通过启动的Jvm去访问对应版本的daemon.Jvm进程- 若没有找到,则启动一个daemon,连接daemon
- 本质:在安装目录下,安装一个很小的jar包和一个脚本,用来下载真正的gradle的discription
- 相关指令:
- gradle wrapper
- 作用:开发时,保持版本一致;在未安装gradle的机器上执行,
-
GradleUserHome
- 默认路径在
~/.gradle/
,不建议使用本地maven的m2替代,因为原本的.gradle目录下的模块分的很清晰,功能明确 - 如果启动时,指定参数,使用别的目录代替
GradleUserHome
,后果是每次构建需要重新下载插件与依赖到新的目录 - 默认情况下,gradle运行时,除了和项目打交道,还有当前项目构建的全新的GradleUserHome目录,所有jar包都得重新下载
目录 desc init.d 项目运行前,仓库替换 wrapper gradle wrapper
指令运行后,下载的安装包会放在此处caches 类似于maven的 .m2
,但是除了本地仓库的包以外,还有其他东西,它会进行自动清理 - 默认路径在
-
Daemon(守护进程)
- 项目启动时,会开启一个client,然后启动一个daemon,通过client向daemon收发请求,项目关闭,client关闭,daemon保持启动,有类似项目再次部署时,会直接通过新的client访问已经启动的daemon,所以速度很快,默认daemon不使用3小时后关闭;不同项目兼容性考虑,也可使用
--no-daemon
启动项目,就没有速度优势了 - 手动停止daemon,
gradle wrapper --stop
- 项目启动时,会开启一个client,然后启动一个daemon,通过client向daemon收发请求,项目关闭,client关闭,daemon保持启动,有类似项目再次部署时,会直接通过新的client访问已经启动的daemon,所以速度很快,默认daemon不使用3小时后关闭;不同项目兼容性考虑,也可使用
Gradle构建
Gradle生命周期
- 生命周期介绍
-
Initialization
- 读取项目信息,确定是单项目还是多项目工程,然后确认哪些项目是要参与进来,并为他们创建Project 实例,一般我们不会接触
-
Configuration
- 进行配置,从头到尾将build.gradle脚本跑一遍。不运行项目,只是对构建进行一些配置,本质就是对build.gradle执行一次,例如执行哪些任务,运行哪些插件,执行哪些逻辑
-
Execution
- 运行阶段。具体执行哪些task
- 生命周期应用
Task
。task是gardle中最小的任务单元,任务之间可以进行复杂的操作(动态创建任务,多任务间依赖调用)- 用法。task('helloworld',Closure closure),
helloworld
即当前任务的名字,closure
闭包作用是对helloworld
任务进行Configuration
,可以在closure
中调用doLast或dependsOn等方法,在helloworld
的Configuration
期间进行wrapper(例如,调用其他任务,或者动态调用任务等) - dependsOn方法,方法参数为其他任务的名字。多任务中通过该方法可执行所依赖的其他任务
- doLast,在生命周期的configuration阶段,将doLast闭包函数放在任务的最后,
并不执行
,执行任务时,会调用该方法。doFirst相反
- 用法。task('helloworld',Closure closure),
./gradlew help
,任何gradle项目都有一个该task,可以执行此命令观察taks执行的流程是否如预期,tips
使用该命令可以查看到所需依赖下载状态(IDE中只能看到是否配置好依赖,但是无法确定还差多少
完成)
Gradle的核心模型
-
Project
。gradle项目中一切无主的方法都会去Project中查找,如task;若是多项目工程,用project.parent.childProjects
对不同的子项目进行配置或者依赖-
afterEvaluate方法,钩子函数。当前项目的Project实例操作完成后(即在生命周期configure阶段gradle引擎执行完一次build.gradle后,才会执行该方法,并不会因为它位置在最前面就先执行,有趣的是Java的main方法执行顺序是按照方法排列的顺序)进行一些动作,beforeEvaluate是与它对应的钩子函数
-
allprojects方法,对一个多项目工程中,所有Project实例进行的操作
-
file方法,读取文件
-
findProject方法,用名字去查找多项目中某一个项目的Project实例
-
findProperty方法,去查找某一个属性
-
getBuildDir方法,查找在项目下一个名为build目录下临时的构建输出
-
Gradle插件编写入门
-
classpath与gradle
- gradle启动时会启动一个jvm,有自己的classpath;Java项目的classpath在project/src目录下作用
- java项目中有需要的jar包,则需在build.gradle中设置仓库
/** *repositories方法和dependencies方法都是无助的闭包函数,构建时会在gradle的Project的API中找具体实现 *任何grdle项目中的无主方法都在Project的API中 * */ //指定中央仓库 repositories{ mavenCentral() } //项目所需的依赖 dependencies{ compile group:'org.apache.commons',name:'commons-lang3',version:'3.9' }
- 在构建build.gradle时使用Java的或其他非gradle的API,则需将声明仓库和依赖放在buildscript方法中
buildscript{ //指定中央仓库 repositories{ mavenCentral() } //项目所需的依赖 dependencies{ compile group:'org.apache.commons',name:'commons-lang3',version:'3.9' } }
- gradle插件加载顺序
- 在加载build.gradle时,如果有buildSrc目录,则会先加载buildSrc中的内容
- 类中编写插件
- 实现Plugin接口,重写apply方法
- 将项目移至类中
- 调用apply方法,第一是DSL版。后一种是原版
- apply plugin: MyAwesomePlugin
- apply ([plugin:MyAwesomePlugin])
gradle处理jar包原理
-
Gradle 与 Java 项目运行在各自的JVM中,Java 项目中的依赖的jar 包通过build.gradle中的
dependencies
中导入,实际上gradle是将jar添加进了java的classpath中,但是gradle自身的jvm的classpath中并没有导入这样的jar包 -
Gradle在build.gradle中使用第三方jar包或使用自定义的插件有两种方法:
- 方法一(buildscript):在build.gradle中使用buildscript方法,在该方法内部使用
repositories
写jar包仓库,在dependencies
中填jar包信息,并声明生命周期 - 方法二(在项目根目录下创建buildSrc包):初始化buildSrc为一个gradle项目,并且创建目录(mkdir -p src/main/java),在java包自定义插件类,然后将插件类引入项目外部的build.gradle中。项目启动时,gradle在 Configuration阶段扫描build.gradle时,会去引入的插件目录确认(buildSrc)。下方是编写插件的示例
- 方法一(buildscript):在build.gradle中使用buildscript方法,在该方法内部使用
public class MyPlugin implements Plugin<Project>{
@Override
public void apply(Project project){
for(int i = 0;i<10;i++){
project.task("task"+i)
}
}
}