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。

相關文章
相關標籤/搜索