我的學(xué)習(xí)筆記1:JavaPoet——自動化代碼生成
干活一年半了,準(zhǔn)備還是整理一些文檔吧,不然真的干了這么久活不知道自己干了啥(捂臉)
一方面也是因為我水平不如他人,一些東西做不到,很多時候我發(fā)現(xiàn)一些東西基本是我自己根本沒有概念,但是意識到了以后學(xué)起來還是非常快的。
?
JavaPoet是一個例子。這個工具主要用途是提供Java代碼的自動化生成。功能上比較輕量級,jar包放進(jìn)來就能用??梢砸越咏a書寫的方式書寫自動化代碼。
?
項目頁面:https://github.com/square/javapoet
直接在git上下載或者用maven都可以。
主要介紹讀readme可以懂個大概。
我這里簡單記錄一下自己是怎么使用這個功能的。
?
一般構(gòu)建java文件需要準(zhǔn)備以下部分的代碼:
FieldSpec:成員變量代碼
樣例:
可以生成:
?
MethodSpec: 成員方法代碼
樣例:
可以生成:
?
TypeSpec:類代碼(基于MethodSpec和FieldSpec等)
樣例:
將生成一個包含有之前樣例成員變量與成員方法的類代碼
?
JavaFile:java文件代碼(基于TypeSpec)
樣例:
?
生成的java文件將輸出到src/my/pac/HelloClass.java
?
按順序整理四個部分的代碼,即可順利完成java文件的自動生成。
?
使用過程中主要的關(guān)鍵字:
$T : 最重要的關(guān)鍵字,輸出一個class,并且自動添加其import,可以直接使用當(dāng)前代碼里存在的class對象,也可以定義包名和類名來定義一個尚不存在的對象
使用例:
生成代碼:
$N: 引用一個已經(jīng)存在的JavaPoet相關(guān)對象,將其定義的name輸出
使用例:
生成代碼:
$L: 將指定的類型的string直接輸出
$S: 將指定的類型包裝成雙引號string值輸出
兩者的區(qū)別可以通過以下使用例說明:
生成代碼:
?
一些代碼細(xì)節(jié):
輸出沒有出現(xiàn)過的類:
使用ClassName.get方法,例如:
生成代碼:
?
輸出帶有<T>模板相關(guān)的類:
生成代碼:
?
應(yīng)用場景:
1.使用AbstractProcessor進(jìn)行注解預(yù)處理時,可以使用JavaPoet進(jìn)行注解代碼相關(guān)生成
?
似乎是網(wǎng)上常見的JavaPoet應(yīng)用場景,我這里還在思考AbstractProcessor運行時不知道能不能獲得足夠的對象反射信息,準(zhǔn)備后續(xù)學(xué)習(xí);
如果是不太需要反射信息就能直接生成的代碼,可以使用JavaPoet簡單生成
?
2.直接寫到項目代碼里另開main方法進(jìn)行代碼生成。
?
我在現(xiàn)在的工作中是這么處理的,直接將JavaPoet生成代碼的流程寫到項目目錄里,利用Class反射信息獲取需要批量生成的Class對象反射信息(例如field,method,parameter等),生成相關(guān)代碼寫入到項目工程下。好處是可以直接利用工程代碼反射信息,壞處是必須執(zhí)行兩遍java代碼,第一遍是生成,第二遍是啟動。
生成部分的代碼可以分離,不在最終jar包里保存。
?
生成代碼時如果產(chǎn)生了錯誤,可能導(dǎo)致后續(xù)build不能完全成功,可以調(diào)節(jié)運行模式在不全部通過編譯時也能運行成功編譯部分的class代碼,在idea下,運行方法為在啟動設(shè)置里設(shè)定“Build, no error check”來實現(xiàn)
?
我使用感覺JavaPoet的優(yōu)點:輕量,生成代碼直接簡單,可以靈活應(yīng)對各種代碼生成需求
?JavaPoet不能做到修改已有代碼。JavaPoet只能生成新代碼,不能改變已有的代碼,也不能識別Java反射以外的信息。
?