capt 正式開源

capt 全稱 Class Annotation Processor Tool闽晦,是作者基于 ASMAndroid Transform API 打造的 Android 平臺(tái)的字節(jié)碼的注解處理工具溯捆。

起源

apt

capt 的靈感有很大一部分來自于 apt。作為一個(gè) Android 開發(fā)者,雖然 apt 已經(jīng)足夠強(qiáng)大哈蝇,但是有個(gè)缺陷一直是我們的痛點(diǎn):只支持源碼圃郊。

Android 日常開發(fā)中,大量的依賴了第三方庫如 AAR / JAR且改,而他們是已經(jīng)編譯成了 class 字節(jié)碼验烧,而 apt 僅支持源碼級(jí)別的注解處理,因?yàn)槲覀儾坏貌煌ㄟ^很多曲折的方式來實(shí)現(xiàn)原本簡單的邏輯又跛。

舉個(gè)例子:阿里開源的 ARouter碍拆,在早期只有 apt 的版本中對(duì)模塊化的處理是通過顯式的添加模塊參數(shù)來實(shí)現(xiàn)的,在新版中也通過注冊 Android Transform API 在打包過程中修改部分字節(jié)碼打到目的。

Lancet

Lancet 是作者在早些時(shí)候在 eleme 開源的 Android AOP 框架感混,就是基于 Transform API 來實(shí)現(xiàn)的端幼。由于 GitHub eleme 組織的廢棄,在幾個(gè)月前作者創(chuàng)建了獨(dú)立的 Lancet 項(xiàng)目并規(guī)劃 Lancet2 的開發(fā)弧满。在思考的過程中婆跑,覺得僅僅是 Lancet2 還不夠酷,有以下幾個(gè)原因:

  1. 注解是固定的幾種庭呜,使用很受限制
  2. 無論是 Lancet2 還是 Lancet1 都有大量重復(fù)的代碼滑进,浪費(fèi)在主流程的無關(guān)邏輯上

于是作者萌生了一個(gè)想法,我們能不能做一個(gè)工具募谎,只做注解處理和代碼轉(zhuǎn)換的分發(fā)邏輯扶关,具體的業(yè)務(wù)邏輯由插件完成。

說干就干数冬,于是 capt 誕生了节槐。

capt

相比 apt,capt 除了提供注解處理之外拐纱,還允許多個(gè)插件鏈?zhǔn)降匦薷拿總€(gè)類的字節(jié)碼铜异。
同時(shí) capt 有以下幾大特性:

完全同步的 Variant

annotationProcessor類似, capt 會(huì)為每個(gè)SourceSet / BuildType / ProductFlavor創(chuàng)建對(duì)應(yīng)的Configuration,你可以用如下的方式戳玫,根據(jù)不同的構(gòu)建類型熙掺,來使用不同的 capt 插件:

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

Application & Library

capt 同時(shí)支持 Android Application 和 Library 的注解處理和注入代碼:

  • Application: 所有的 runtime class
  • Library: 僅該 Library 自身

APK & AndroidTest

capt 支持打普通 APK 和 AndroidTest 時(shí)注入:

  • APK: 打普通 APK 時(shí)會(huì)傳遞所有的 APK 中的類
  • AndroidTest: AndroidTest 打包時(shí)只會(huì)傳遞所有 androidTest 目錄下的類

靈活的參數(shù)

capt 會(huì)為每個(gè)注冊的插件創(chuàng)建一個(gè) Gradle Extension 對(duì)象,可以傳入任意形式的參數(shù)咕宿,在插件的生命周期傳遞給插件币绩,同時(shí)每個(gè) Extension 也會(huì)內(nèi)置插件的公共參數(shù),如優(yōu)先級(jí)(可覆蓋插件中聲明的默認(rèn)優(yōu)先級(jí))府阀、作用域(Assemble | AndroidTest)等缆镣。

極致的增量更新

capt 會(huì)針對(duì)每個(gè) Variant 有自身的緩存,記錄類圖试浙、插件和插件的修改的類等元信息董瞻。

注解處理

capt 會(huì)解析類圖,分析類圖中類的的變化(添加田巴、修改钠糊、刪除),因此 capt 要求所有的插件注解處理器都要支持增量解析壹哺,因此 capt 對(duì)打包時(shí)間的影響很小抄伍。并且性能一直是 cpat 持續(xù)追求的目標(biāo)

當(dāng)然有得有失,因?yàn)樵谠隽磕J较鹿芟凶⒔獾念悰]有發(fā)生變化是不會(huì)傳遞到注解處理器中的截珍,因此需要每個(gè)插件自己去實(shí)現(xiàn)本地緩存的邏輯攀甚。

類轉(zhuǎn)換

capt 遵循最小原則,因此類轉(zhuǎn)換有3步:

  1. capt 會(huì)詢問每個(gè)插件需要哪些類(全量岗喉、增量秋度、無),以及是否解析額外的類
  2. 如果上次構(gòu)建過程中的插件被移除(移除插件不會(huì)打斷增量構(gòu)建流程钱床,增加會(huì))荚斯,capt 會(huì)額外添加被移除插件修改過的類
  3. 最后 capt 會(huì)匯總上面的信息,并據(jù)此來分發(fā)類的轉(zhuǎn)換流程诞丽。

豐富的 API

capt 在插件的生命周期會(huì)提供豐富的 API鲸拥,如類結(jié)構(gòu)圖、上下文僧免、甚至于ClassLoader,讓每個(gè)插件的奇思妙想都能夠?qū)崿F(xiàn)捏浊。如果有更多更好的想法也可以提 Issue & PR 哦懂衩。

對(duì) ASM 的高度支持

capt 允許在類轉(zhuǎn)換前對(duì) ClassReader 和 ClassWriter 請求額外的標(biāo)志位,從而提供了最大的靈活性金踪,同時(shí)默認(rèn)都為 0 以期最佳性能浊洞。

并且 capt 為 ClassWriter.COMPUTE_FRAME 生成了獨(dú)特的 ClassLoader,開發(fā)者不再需要糾結(jié)于代碼中的計(jì)算棧幀信息的問題胡岔。

未來規(guī)劃

  • 基于 capt 開發(fā) Lancet2
  • 持續(xù)優(yōu)化性能
  • 更多豐富的 API

開源地址

https://github.com/CoffeePartner/capt

如果覺得 capt 還不錯(cuò)法希,請給 capt 一個(gè) Star!
歡迎 Issue & PR靶瘸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苫亦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子怨咪,更是在濱河造成了極大的恐慌屋剑,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诗眨,死亡現(xiàn)場離奇詭異唉匾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匠楚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門巍膘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芋簿,你說我怎么就攤上這事峡懈。” “怎么了益咬?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵逮诲,是天一觀的道長帜平。 經(jīng)常有香客問我,道長梅鹦,這世上最難降的妖魔是什么裆甩? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮齐唆,結(jié)果婚禮上嗤栓,老公的妹妹穿的比我還像新娘。我一直安慰自己箍邮,他們只是感情好茉帅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锭弊,像睡著了一般堪澎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上味滞,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天樱蛤,我揣著相機(jī)與錄音,去河邊找鬼剑鞍。 笑死昨凡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚁署。 我是一名探鬼主播便脊,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼光戈!你這毒婦竟也來了哪痰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤田度,失蹤者是張志新(化名)和其女友劉穎妒御,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镇饺,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乎莉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奸笤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惋啃。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖监右,靈堂內(nèi)的尸體忽然破棺而出边灭,到底是詐尸還是另有隱情,我是刑警寧澤健盒,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布绒瘦,位于F島的核電站称簿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惰帽。R本人自食惡果不足惜憨降,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望该酗。 院中可真熱鬧授药,春花似錦、人聲如沸呜魄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爵嗅。三九已至娇澎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睹晒,已是汗流浹背九火。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留册招,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓勒极,卻偏偏與公主長得像是掰,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辱匿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容