深入Dagger:JavaPoet的使用

前言

最近在用Dagger開發(fā)應用,Dagger是google在square的基礎上去反射的依賴注入框架凌箕。
Dagger會根據(jù)定義的注解在編譯階段根據(jù)依賴注入的配置生成相應的代碼,來減少運行期間反射的開銷荠呐。
Dagger依賴了JavaPoet和JavaFormat來輔助實現(xiàn)生成代碼募疮,這里主要介紹下JavaPoet的內(nèi)容和使用。

JavaPoet

JavaPoet這樣定義自己的項目缆毁。

Use beautiful Java code to generate beautiful Java code

所以JavaPoet定義了一系列類來盡可能優(yōu)雅的描述java源文件的結(jié)構(gòu)。觀察JavaPoet的代碼主要的類可以分為以下幾種:

  • Spec 用來描述Java中基本的元素到涂,包括類型脊框,注解,字段践啄,方法和參數(shù)等浇雹。
    • AnnotationSpec
    • FieldSpec
    • MethodSpec
    • ParameterSpec
    • TypeSpec
  • Name 用來描述類型的引用,包括Void屿讽,原始類型(int昭灵,long等)和Java類等。
    • TypeName
    • ArrayTypeName
    • ClassName
    • ParameterizedTypeName
    • TypeVariableName
    • WildcardTypeName
  • CodeBlock 用來描述代碼塊的內(nèi)容伐谈,包括普通的賦值烂完,if判斷,循環(huán)判斷等诵棵。
  • JavaFile 完整的Java文件抠蚣,JavaPoet的主要的入口。
  • CodeWriter 讀取JavaFile并轉(zhuǎn)換成可閱讀可編譯的Java源文件履澳。

示例

下面通過一個例子來完整的實現(xiàn)一個Java類的定義嘶窄。
通過下面的maven依賴可以引用JavaPoet包怀跛。

    <dependency>
        <groupId>com.squareup</groupId>
        <artifactId>javapoet</artifactId>
        <version>1.7.0</version>
    </dependency>

完整的代碼放在Github。這里介紹一下主要的方法柄冲。

  1. AnnotationSpec 添加MyAnnotation的注解吻谋,然后設置屬性hello=world
    private static AnnotationSpec makeAnnotationSpec() {
        AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get("org.wcong.test.poet", "MyAnnotation"));
        CodeBlock.Builder codeBlockBuilder = CodeBlock.builder().add("$S", "world");
        builder.addMember("hello", codeBlockBuilder.build());
        return builder.build();
    }
  1. FieldSpec 創(chuàng)建hello的字段并初始化為“world”现横。
    private static FieldSpec makeFieldSpec() {
        FieldSpec.Builder fileSpecBuilder = FieldSpec.builder(String.class, "hello", Modifier.PRIVATE);
        fileSpecBuilder.initializer(CodeBlock.of("\"world\""));
        return fileSpecBuilder.build();
    }
  1. MethodSpec 創(chuàng)建getHello,setHello,toString方法漓拾。
    toString使用了ControlFlow判斷了hello不等于null,返回"hello world"戒祠,等于null的時候返回空晦攒。
    private static MethodSpec makeToStringMethod() {
        MethodSpec.Builder toStringBuilder = MethodSpec.methodBuilder("toString");
        toStringBuilder.addModifiers(Modifier.PUBLIC);
        toStringBuilder.returns(TypeName.get(String.class));
        CodeBlock.Builder toStringCodeBuilder = CodeBlock.builder();
        toStringCodeBuilder.beginControlFlow("if( hello != null )");
        toStringCodeBuilder.add(CodeBlock.of("return \"hello \"+hello;\n"));
        toStringCodeBuilder.nextControlFlow("else");
        toStringCodeBuilder.add(CodeBlock.of("return \"\";\n"));
        toStringCodeBuilder.endControlFlow();
        toStringBuilder.addCode(toStringCodeBuilder.build());
        return toStringBuilder.build();
    }
    private static MethodSpec makeSetMethod() {
        MethodSpec.Builder setMethodSpecBuilder = MethodSpec.methodBuilder("setHello");
        setMethodSpecBuilder.addModifiers(Modifier.PUBLIC);
        setMethodSpecBuilder.returns(TypeName.VOID);
        ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(TypeName.get(String.class), "hello");
        setMethodSpecBuilder.addParameter(parameterBuilder.build());
        setMethodSpecBuilder.addCode(CodeBlock.builder().add("this.hello = hello;\n").build());
        return setMethodSpecBuilder.build();
    }
    private static MethodSpec makeGetMethod() {
        MethodSpec.Builder getMethodSpecBuilder = MethodSpec.methodBuilder("getHello");
        getMethodSpecBuilder.addModifiers(Modifier.PUBLIC);
        getMethodSpecBuilder.returns(TypeName.get(String.class));
        getMethodSpecBuilder.addCode(CodeBlock.builder().add("return hello;\n").build());
        return getMethodSpecBuilder.build();
    }
  1. JavaFile JavaPoet的主入口,用來描述Java源文件得哆。
    public static void main(String[] args) {
        TypeSpec.Builder typeSpecBuilder = TypeSpec.classBuilder("JavaFile");
        typeSpecBuilder.addAnnotation(makeAnnotationSpec());
        typeSpecBuilder.addField(makeFieldSpec());
        typeSpecBuilder.addMethods(makeMethodSpec());
        JavaFile.Builder javaFileBuilder = JavaFile.builder("org.wcong.test.poet", typeSpecBuilder.build());
        System.out.println(javaFileBuilder.build().toString());
    }

運行后輸出下面的信息,就是一個完整的類文件了

package org.wcong.test.poet;

import java.lang.String;

@MyAnnotation(
    hello = "world"
)
class JavaFile {
  private String hello = "world";

  public String getHello() {
    return hello;
  }

  public void setHello(String hello) {
    this.hello = hello;
  }

  public String toString() {
    if( hello != null ) {
      return "hello "+hello;
    } else {
      return "";
    }
  }
}

結(jié)語

dagger使用JavaPoet來保存自動生成的類的信息哟旗,并通過JavaFormat來格式化生成的Java源文件贩据。后面會介紹關(guān)于JavaFormat的內(nèi)容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末闸餐,一起剝皮案震驚了整個濱河市饱亮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舍沙,老刑警劉巖近上,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拂铡,居然都是意外死亡壹无,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門感帅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斗锭,“玉大人,你說我怎么就攤上這事失球♂牵” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵实苞,是天一觀的道長豺撑。 經(jīng)常有香客問我,道長黔牵,這世上最難降的妖魔是什么聪轿? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮猾浦,結(jié)果婚禮上屹电,老公的妹妹穿的比我還像新娘阶剑。我一直安慰自己,他們只是感情好危号,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布牧愁。 她就那樣靜靜地躺著,像睡著了一般外莲。 火紅的嫁衣襯著肌膚如雪猪半。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天偷线,我揣著相機與錄音磨确,去河邊找鬼。 笑死声邦,一個胖子當著我的面吹牛乏奥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亥曹,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼邓了,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了媳瞪?” 一聲冷哼從身側(cè)響起骗炉,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蛇受,沒想到半個月后句葵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡兢仰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年乍丈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片把将。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡诗赌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秸弛,到底是詐尸還是另有隱情铭若,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布递览,位于F島的核電站叼屠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绞铃。R本人自食惡果不足惜镜雨,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望儿捧。 院中可真熱鬧荚坞,春花似錦挑宠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诡挂,卻和暖如春碎浇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背璃俗。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工奴璃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人城豁。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓苟穆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親唱星。 傳聞我的和親對象是個殘疾皇子雳旅,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)魏颓,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗吱晒。 張土汪:刷leetcod...
    土汪閱讀 12,737評論 0 33
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程甸饱,因...
    小菜c閱讀 6,365評論 0 17
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關(guān)的語法仑濒,內(nèi)部類的語法叹话,繼承相關(guān)的語法,異常的語法墩瞳,線程的語...
    子非魚_t_閱讀 31,597評論 18 399
  • 一 端午將至喉酌,原來就是按照農(nóng)歷計算热凹,2017年也將很快灑脫過半。 無法抵擋的歲月洪流泪电,真是永遠在激蕩向前般妙。 每到端...
    長風18閱讀 2,283評論 0 1