小春网

 找回密码
 注册账号
查看: 2259|回复: 35
收起左侧

几个老爷们,天天说IT,有完没完? 特别是那谁

[复制链接]
 楼主| 发表于 2017-3-28 15:13:57 来自手机 | |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册账号

x
如题
发表于 2017-3-28 15:15:40 |


也不聊聊女人

搞的我都插不上嘴。。。。
发表于 2017-3-28 15:31:46 来自手机 |
小剛 发表于 2017-3-28 15:15


也不聊聊女人

刚哥好久不见
发表于 2017-3-28 15:32:10 |
同感。
虽然俺也算是干IT的,对这些帖子实在是没啥兴趣。
本来就是上班偷懒来上小春滴,结果这里也是技术呀年收呀一大堆,看着费劲。
要不就是互相黑来黑去。

就没点轻松的话题?
发表于 2017-3-28 15:34:09 |

恩,好久不见。。。。。。

之前忙,现在闲下来点了

看你混的挺好的。。。。羡慕。。。。。
头像被屏蔽
发表于 2017-3-28 15:40:06 |
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| 发表于 2017-3-28 15:51:52 来自手机 |
各位IT大侠,实在抱歉,我太直接了。只是满屏幕ITITITITI天
头像被屏蔽
发表于 2017-3-28 15:53:24 |
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| 发表于 2017-3-28 16:00:45 来自手机 |
日本干IT的人太多,这话题最终都失去最初的意义,大家都不和谐
发表于 2017-3-28 16:01:11 |
陆续续一年多,总是有人问 Gradle 构建,总是发现很多人用 Gradle 是迷糊状态的,于是最近准备来一个“Gradle 庖丁解牛”系列,一方面作为自己的总结,一方面希望真的能达到标题所示效果,同时希望通过该系列达到珍惜彼此时间的目的,因为目前市面上关于 Gradle 的教程都是在教怎么配置和怎么编写插件,很少有说明 Gradle 自己到底是个啥玩意的,还有是如何工作的,本系列以官方 release 3.4 版本为基础。

废话不多说,标题也表明了本篇所总结的内容 —— 构建源头源码浅析,不懂啥叫 Gradle 和 Groovy 的请先移步我以前文章《Groovy 脚本基础全攻略》和《Gradle 脚本基础全攻略》,免得这一系列也看不明白咋回事。不过还是要先打个预防针,竟然还有人觉得 Gradle 只能构建 Android App,这 TM 就尴尬了,我想说 Gradle 就是一套脚手架,你想干啥玩意都可以,就看你想不想干,他就是个自动化构建框架,你整明白它的核心以后,他的插件你只用依据规则使用即可,譬如用来构建 Android 的 apply plugin: 'com.android.application' 只是它的一个小插件而已,实质就看你想搞啥了,Java、Web、JS、C 等等都可以用它构建;而整明白它原理核心之一就是你得先整明白他的规则,也就是本文所总结讨论的内容。

2 基础技能叨叨叙

所谓基础技能就是一些铺垫,既然要说 Gradle 构建系列了,我们有必要知道 Gradle 相关的一些基本命令,方便下面演示时使用(注意:如下命令是针对安装 gradle 并配置环境变量的情况下执行,你如果做 Android 开发的话,Ubuntu 直接将如下所有 gradle 替换为 ./gradlew 即可,这样就可以用包装特性了,至于包装是咋回事后面会说),关于其他命令请呼叫 help 或者查看官方 User Guide 的 Using the Gradle Command-Line。

其实上面脚本的作用就是对 Gradle 的一个包装,保证任何机器都可以运行这个构建,即使这个机器没有安装 Gradle 或者安装的 Gradle 版本不兼容匹配,如果没装或者不兼容就会根据 gradle-wrapper.properties 里的配置下载特定版本,下载的包放在 $USER_HOME/.gradle/wrapper/dists 目录下,所以我们有时候第一次通过 gradlew 包装脚本执行构建时总会看到正在下载一个 zip 文件,实质就是在下 gradle-wrapper.properties 中指定的 zip 包。
gradlew 有一个非常人性化和牛逼的特点,解决了几种坑爹的问题,譬如团队开发保证 Gradle 构建版本一致性、gradle-wrapper.properties 下载地址方便切换到公司内部服务器等(甚至可以先通过 gradle.properties 文件配置公司服务器的帐号密码或者验证信息,然后在 gradle-wrapper.properties 中配置distributionUrl=https://username:password@somehost/path/to/gradle-distribution.zip,这样就可以达到公司内网加认证下载的双重安全了)。
gradlew 由来的最终原理其实是通过 Gradle 预置的 Wrapper (继承自 DefaultTask )来实现的(AS 内部默认实现了自动生成而已)

运行 gradle createWrapper 就能生成上面描述的几个文件。而关于 Gradle 的 Wrapper 可以参考 DSL Reference 的 Wrapper 和 JavaDoc 的 Wrapper API,里面提供了一堆属性设置下载地址、解压路径、 gradleVersion 等,你也可以在 distributionUrl 中通过 ${gradleVersion} 来使用你设置的 DSL 变量,这里暂时不再展开。

说完命令我们接着说说 Groovy、DSL、Gradle 之间的关系,首先一定要明确,Groovy 不是 DSL,而是通用的编程语言,类似 Java、C++ 等,就是一种语言;但 Groovy 对编写 DSL 提供了很牛逼的支持,这些支持都源自 Groovy 自己语法的特性,比如闭包特性、省略分号特性、有参方法调用省略括弧特性、属性默认实现 getter、setter 方法特性等,当然,作为 Android 开发来说,Gradle 构建 Android 应用实质也是基于 Groovy 编写的 DSL,DSL 存在的意义就在于简化编写和阅读。

而 Gradle 的实质就是一个基于 Groovy 的框架了,也就是说我们得按照他的约束来玩了,和我们平时 Android 开发使用框架类似,一旦引入框架,我们就得按照框架的写法来规规矩矩的编写。Gradle 这个框架只负责流程约定,处理细节是我们自己的事,就像我们编译 Android App 时基于 Gradle 框架流程引入 apply plugin: 'com.android.application' 构建插件一样,具体做事是我们插件再约束的,插件又对我们简化了配置,我们只用基于 Gradle 框架和相关插件进行构建配置。

了所以简单粗暴的解释就是, Groovy 是一门语言,DSL 就是一种特定领域的配置文件,Gradle 就是基于 Groovy 的一种框架,就像我们以前做 Android 开发使用 Ant 构建一样,build.xml 就可以粗略的理解为 Ant 的 DSL 配置,所以我们编写 build.xml 时会相对觉得挺轻松(和后来的 Gradle 还是没法比的)。

搞清了他们之间的关系后我们就要深入看看为啥是这样了,因为关于 Gradle 构建现在中文网上的教程要么是教你如何配置 DSL 属性,要么就是教你如何使用 Groovy 去拓展自己的特殊 task,或者是教你怎么编写插件,却几乎没人提到 Gradle 这个构建框架的本质,所以使用起来总是心里发慌,有种不受控制的感觉。

3 Gradle 源码源头分析

还记得我们前一小节讲的 gradlew 么,追踪溯源就从它开始,以前我也是出于好奇就去看了下它,发现这个 shell 脚本前面其实就是干了一堆没事干的事,大招就在它的最后一句
到这里你可以暂时松口气了,上面 config 等等一堆都是在做准备,说白了就是各种列表注册都放好,然后 DefaultServiceRegistry 的 get(…) 系列方法实质都是通过 doGet(Type serviceType) 的 invok 方法调用等。接着让我们把目光移到上面运行 gradle taskName 命令时分析的 BuildActionsFactory 的 runBuildInProcess(…) 方法,我们在该方法中调用 runBuildAndCloseServices(…) 方法时第三个参数传递的是 globalServices.get(BuildExecuter.class), 也就是调用了 DefaultServiceRegistry 的 get(BuildExecuter.class) 方法,刚刚说了 DefaultServiceRegistry 的 get(…) 实质就是 invoke 一个方法,在这里 serviceType 参数是 BuildExecuter.class,所以调用的就是 ToolingGlobalScopeServices 的 createBuildExecuter(…) 方法,ToolingGlobalScopeServices 是 LauncherServices 的 registerGlobalServices(…) 方法实例化的,而 LauncherServices implements PluginServiceRegistry 又是刚刚上面分析 GlobalScopeServices 的 configure(…) 方法里被实例化添加的,LauncherServices 的 registerGlobalServices(…) 方法也是在那调用的。

绕了一圈真是折腾,突然发现累觉不爱,觉得 Gradle 框架中 DefaultServiceRegistry 类的设计真的是挺颠覆我认知的,虽然没啥黑科技,但是这个设计思路真的是坑爹,很容易绕懵逼,好在后来整明白了,真想说句 ZNMKD。好了,牢骚也发完了,下面该正题了,我们接着上面说的去看看 LauncherServices 内部 ToolingGlobalScopeServices 的 createBuildExecuter(…) 方法,一贯做法,关注主线,咱们会发现这方法最主要的就是层层简单代理模式包装实例化 BuildActionExecuter 对象,最关键的就是实例化了 InProcessBuildActionExecuter 对象,这个对象就一个 execute 方法(这个 execute 方法被调用的地方就在上面分析的 BuildActionsFactory 的 runBuildInProcess 方法返回的 RunBuildAction 对象的 run 方法中,RunBuildAction 对象的 run 方法又是前面分析的源头触发的)

4 总结

为了 Gradle 庖丁解牛系列做铺垫,本篇主要进行了 Gradle 基础铺垫说明总结,后面对 Gradle 框架自身初始化(非构建生命周期的初始化,要区分)的核心流程进行了分析,通过本文我们至少应该知道如下:

Gradle 只是一个构建框架,而且大多数代码是 Java 和 Groovy 编写。
gradlew 是 gradle 的一个兼容包装工具。
执行 gradle 或者 gradlew 命令开始进行构建生命周期前做的第一步是对 Gradle 框架自身的初始化(本文浅析内容)。
有了这一篇的铺垫,下面几篇我们会以此分析继续,不过主线都是基于执行一个 gradle taskName 命令,所以如果想看懂这个系列文章,建议先补习下 Gradle 构建基础。

^v^当然咯,如果觉得对自己有帮助,不妨扫描打赏一点买羽毛球的票子,是一种动力也是一种鼓励,谢谢。
小春网
常务客服微信
微信订阅号
手机客户端
扫一扫,查看更方便! 快速回复 返回顶部 返回列表