capt 正式开源

capt 全称 Class Annotation Processor Tool,是作者基于 ASMAndroid Transform API 打造的 Android 平台的字节码的注解处理工具。

起源

apt

capt 的灵感有很大一部分来自于 apt。作为一个 Android 开发者,虽然 apt 已经足够强大,但是有个缺陷一直是我们的痛点:只支持源码

Android 日常开发中,大量的依赖了第三方库如 AAR / JAR,而他们是已经编译成了 class 字节码,而 apt 仅支持源码级别的注解处理,因为我们不得不通过很多曲折的方式来实现原本简单的逻辑。

举个例子:阿里开源的 ARouter,在早期只有 apt 的版本中对模块化的处理是通过显式的添加模块参数来实现的,在新版中也通过注册 Android Transform API 在打包过程中修改部分字节码打到目的。

Lancet

Lancet 是作者在早些时候在 eleme 开源的 Android AOP 框架,就是基于 Transform API 来实现的。由于 GitHub eleme 组织的废弃,在几个月前作者创建了独立的 Lancet 项目并规划 Lancet2 的开发。在思考的过程中,觉得仅仅是 Lancet2 还不够酷,有以下几个原因:

  1. 注解是固定的几种,使用很受限制
  2. 无论是 Lancet2 还是 Lancet1 都有大量重复的代码,浪费在主流程的无关逻辑上

于是作者萌生了一个想法,我们能不能做一个工具,只做注解处理和代码转换的分发逻辑,具体的业务逻辑由插件完成。

说干就干,于是 capt 诞生了。

capt

相比 apt,capt 除了提供注解处理之外,还允许多个插件链式地修改每个类的字节码。
同时 capt 有以下几大特性:

完全同步的 Variant

annotationProcessor类似, capt 会为每个SourceSet / BuildType / ProductFlavor创建对应的Configuration,你可以用如下的方式,根据不同的构建类型,来使用不同的 capt 插件:

dependencies {
    capt project(":xx")
    capt "xx:xx:1.0"
    capt files("...")
    releaseCapt ...
    androidTestCapt ...
}

Application & Library

capt 同时支持 Android Application 和 Library 的注解处理和注入代码:

  • Application: 所有的 runtime class
  • Library: 仅该 Library 自身

APK & AndroidTest

capt 支持打普通 APK 和 AndroidTest 时注入:

  • APK: 打普通 APK 时会传递所有的 APK 中的类
  • AndroidTest: AndroidTest 打包时只会传递所有 androidTest 目录下的类

灵活的参数

capt 会为每个注册的插件创建一个 Gradle Extension 对象,可以传入任意形式的参数,在插件的生命周期传递给插件,同时每个 Extension 也会内置插件的公共参数,如优先级(可覆盖插件中声明的默认优先级)、作用域(Assemble | AndroidTest)等。

极致的增量更新

capt 会针对每个 Variant 有自身的缓存,记录类图、插件和插件的修改的类等元信息。

注解处理

capt 会解析类图,分析类图中类的的变化(添加、修改、删除),因此 capt 要求所有的插件注解处理器都要支持增量解析,因此 capt 对打包时间的影响很小。并且性能一直是 cpat 持续追求的目标

当然有得有失,因为在增量模式下,含有注解的类没有发生变化是不会传递到注解处理器中的,因此需要每个插件自己去实现本地缓存的逻辑。

类转换

capt 遵循最小原则,因此类转换有3步:

  1. capt 会询问每个插件需要哪些类(全量、增量、无),以及是否解析额外的类
  2. 如果上次构建过程中的插件被移除(移除插件不会打断增量构建流程,增加会),capt 会额外添加被移除插件修改过的类
  3. 最后 capt 会汇总上面的信息,并据此来分发类的转换流程。

丰富的 API

capt 在插件的生命周期会提供丰富的 API,如类结构图、上下文、甚至于ClassLoader,让每个插件的奇思妙想都能够实现。如果有更多更好的想法也可以提 Issue & PR 哦。

对 ASM 的高度支持

capt 允许在类转换前对 ClassReader 和 ClassWriter 请求额外的标志位,从而提供了最大的灵活性,同时默认都为 0 以期最佳性能。

并且 capt 为 ClassWriter.COMPUTE_FRAME 生成了独特的 ClassLoader,开发者不再需要纠结于代码中的计算栈帧信息的问题。

未来规划

  • 基于 capt 开发 Lancet2
  • 持续优化性能
  • 更多丰富的 API

开源地址

https://github.com/CoffeePartner/capt

如果觉得 capt 还不错,请给 capt 一个 Star!
欢迎 Issue & PR。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容