capt 正式开源

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

起源

apt

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

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

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

开源地址

github.com/CoffeePartn…

若是以为 capt 还不错,请给 capt 一个 Star! 欢迎 Issue & PR。

相关文章
相关标签/搜索