您好,登錄后才能下訂單哦!
作為程序猿,每天都在寫代碼,但是有沒有想過通過代碼對寫好的代碼”動點手腳”呢?今天就與大家分享——
先拋一個問題:如何將圖一代碼改寫為圖二?
此題需要把代碼中和程序邏輯無關的字符串提取出來,替換為id。比如個推日志輸出類,縮短日志描述信息后,輸出的日志就隨之變短,根據映射表可以恢復真實原始日志。
你可能會想通過萬能的“正則表達式”匹配替換,但當代碼較為復雜時(如下圖所示),使用“正則表達法”則會將問題復雜化,難以確保所有代碼的完美覆蓋并匹配。若通過AST語法樹,可以很好地解決此問題。
AST(Abstract syntax tree)即為“抽象語法樹”,簡稱語法樹,指代碼在計算機內存的一種樹狀數據結構,便于計算機理解和閱讀。
一般只有語言的編譯器開發人員或者從事語言設計的人員才涉及到語法樹的提取和處理,所以很多人會對這個概念比較陌生。
上圖即為語法樹,左邊樹的節點對應右邊相同顏色覆蓋的代碼塊。
眾所周知,Java 編譯流程(上圖)中也有對AST語法樹的提取處理,那是否可以在此環節操作語法樹呢?由于編譯鏈代碼棧太深,鮮有對外的接口和文檔,使得其可操作性不強。不過,如果采用迂回戰術如下圖所示,可以對其進行操作。
個推log-rewrite項目改寫日志,就是用AST語法樹進行的,流程圖如下圖所示。
先把所有源碼解析為AST語法樹,遍歷每一個編譯單元與單元的類聲明,在類聲明里根據日志方法的簽名找到所有的方法調用,然后遍歷每個方法調用,將方法調用的第二個參數表達式放入遞歸方法,對字符串字面值進行改寫。
對應的代碼較為簡短, 使用github的 Netflix-Skunkworks/rewrite開源庫與kotlin語言,能讀懂Java的你也一定能讀明白。
如果想將日志恢復原樣,可根據前綴、后綴定制正則表達式,逐行匹配替換。如下圖所示。
1、 編譯工具從ant到gradle的切換
此項目起步于ant主流時期,隨著技術日漸成熟,gradle逐漸取代了ant的位置,演變成官方的編譯打包方式。因為歷史原因,若直接將上圖類似預編譯的代碼切換到gradle較為棘手,通過AST語法樹重寫,再用gradle編譯,就可以解決此問題。
上圖的#debug和#mdebug指令,也可以通過AST改寫之后再進行編譯。
2、 自動靜態埋點
代碼中需要運營統計、數據分析等,需要通過代碼埋點進行用戶行為數據收集。傳統的做法是手動在代碼中添加埋點代碼,但此過程較為繁瑣,可能會對業務代碼造成干擾,倘若通過改寫AST語法樹,在編譯打包期添加這種類似的埋點代碼,就可減少不必要的繁瑣過程,使其更加高效。
最后附推薦操作AST類庫鏈接&完整項目源碼地址,希望可以幫助大家打開腦洞,設想更多的應用場景。
推薦操作AST類庫鏈接
https://github.com/Netflix-Skunkworks/rewrite
https://github.com/Javaparser/Javaparser
https://github.com/antlr/antlr4
完整項目源碼地址如下,歡迎fork&start
https://github.com/foxundermoon/log-rewrite
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。