JavaPoet的使用指南小結(jié)
前言
對(duì)于我來說,JavaPoet也是不經(jīng)意間發(fā)現(xiàn)的,日常Android開發(fā)中:
主要使用Mvp+RxJava+Dagger2這套框架
在這套框架里每次寫 Activity 或者 Fragment 就會(huì)寫一套Mvp+Compent+Module,如下圖:
生成內(nèi)容.jpeg
經(jīng)過長時(shí)間的重復(fù)編寫,發(fā)現(xiàn)這一套Mvp+Compent+Module文件,只有名稱是變化的,所以只需要將名稱抽象出來,其他只需模板化,就能生成出上述Java文件.
正當(dāng)想怎么能夠快捷生成Java文件,這時(shí)JavaPoet便出現(xiàn),而且JavaPoet能夠完全滿足需求。
本文主要以JavaPoet的使用方法介紹為主,會(huì)將JavaPoet的基本API都介紹一遍,你也可以理解成JavaPoet的中文簡易教程
JavaPoet的基本介紹
(1)JavaPoet是一款可以自動(dòng)生成Java文件的第三方依賴
(2)簡潔易懂的API,上手快
(3)讓繁雜、重復(fù)的Java文件,自動(dòng)化生成,提高工作效率,簡化流程
JavaPoet的小試牛刀
為了展示JavaPoet的能力,這里以自動(dòng)生成一個(gè)全新的MainActivity為例。
public class MainActivity extends Activity{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
我在使用JavaPoet的時(shí)候,習(xí)慣從外向內(nèi)逐一生成,但是這不是標(biāo)準(zhǔn),這里可以按照自己的方式來理解和生成.
public static void main(String[] args) { ClassName activity = ClassName.get("android.app", "Activity"); TypeSpec.Builder mainActivityBuilder = TypeSpec.classBuilder("MainActivity") .addModifiers(Modifier.PUBLIC) .superclass(activity); ClassName override = ClassName.get("java.lang", "Override"); ClassName bundle = ClassName.get("android.os", "Bundle"); ClassName nullable = ClassName.get("android.support.annotation", "Nullable"); ParameterSpec savedInstanceState = ParameterSpec.builder(bundle, "savedInstanceState") .addAnnotation(nullable) .build(); MethodSpec onCreate = MethodSpec.methodBuilder("onCreate") .addAnnotation(override) .addModifiers(Modifier.PROTECTED) .addParameter(savedInstanceState) .addStatement("super.onCreate(savedInstanceState)") .addStatement("setContentView(R.layout.activity_main)") .build(); TypeSpec mainActivity = mainActivityBuilder.addMethod(onCreate) .build(); JavaFile file = JavaFile.builder("com.test", mainActivity).build(); try { file.writeTo(System.out); } catch (IOException e) { e.printStackTrace(); } }
通過在Main方法中運(yùn)行以上的代碼,就可以直接生成出MainActivity對(duì)象,自上而下的觀察上述代碼,你會(huì)發(fā)現(xiàn)JavaPoet讓java文件變得有邏輯性。
JavaPoet的常用類
- TypeSpec————用于生成類、接口、枚舉對(duì)象的類
- MethodSpec————用于生成方法對(duì)象的類
- ParameterSpec————用于生成參數(shù)對(duì)象的類
- AnnotationSpec————用于生成注解對(duì)象的類
- FieldSpec————用于配置生成成員變量的類
- ClassName————通過包名和類名生成的對(duì)象,在JavaPoet中相當(dāng)于為其指定Class
- ParameterizedTypeName————通過MainClass和IncludeClass生成包含泛型的Class
- JavaFile————控制生成的Java文件的輸出的類
JavaPoet的常用方法
設(shè)置修飾關(guān)鍵字
addModifiers(Modifier... modifiers)
Modifier是一個(gè)枚舉對(duì)象,枚舉值為修飾關(guān)鍵字Public、Protected、Private、Static、Final等等。
所有在JavaPoet創(chuàng)建的對(duì)象都必須設(shè)置修飾符(包括方法、類、接口、枚舉、參數(shù)、變量)。
設(shè)置注解對(duì)象
addAnnotation(AnnotationSpec annotationSpec) addAnnotation(ClassName annotation) addAnnotation(Class<?> annotation)
該方法即為類或方法或參數(shù)設(shè)置注解,參數(shù)即可以是AnnotationSpec,也可以是ClassName,還可以直接傳遞Class對(duì)象。
一般情況下,包含復(fù)雜屬性的注解一般用AnnotationSpec,如果單純添加基本注解,無其他附加屬性可以直接使用ClassName或者Class即可。
設(shè)置注釋
addJavadoc(CodeBlock block) addJavadoc(String format, Object... args)
在編寫類、方法、成員變量時(shí),可以通過addJavadoc來設(shè)置注釋,可以直接傳入String對(duì)象,或者傳入CodeBlock(代碼塊)。
JavaPoet生成類、接口、枚舉對(duì)象
在JavaPoet中生成類、接口、枚舉,必須得通過TypeSpec生成,而classBuilder、interfaceBuilder、enumBuilder便是創(chuàng)建其關(guān)鍵的方法:
創(chuàng)建類: TypeSpec.classBuilder("類名“) TypeSpec.classBuilder(ClassName className) 創(chuàng)建接口: TypeSpec.interfaceBuilder("接口名稱") TypeSpec.interfaceBuilder(ClassName className) 創(chuàng)建枚舉: TypeSpec.enumBuilder("枚舉名稱") TypeSpec.enumBuilder(ClassName className)
繼承、實(shí)現(xiàn)接口
繼承類: .superclass(ClassName className) 實(shí)現(xiàn)接口 .addSuperinterface(ClassName className)
繼承存在泛型的父類
當(dāng)繼承父類存在泛型時(shí),需要使用ParameterizedTypeName
ParameterizedTypeName get(ClassName rawType, TypeName... typeArguments)
返回的ParameterizedTypeName對(duì)象,已經(jīng)被添加泛型信息
方法
addMethod(MethodSpec methodSpec)
通過配置MethodSpec對(duì)象,使用addMethod方法將其添加進(jìn)TypeSpec中。
枚舉
addEnumConstan(String enumValue)
通過addEnumConstan方法添加枚舉值,參數(shù)為枚舉值名稱。
JavaPoet生成成員變量
JavaPoet生成成員變量是通過FieldSpec的build方法生成.
builder(TypeName type, String name, Modifier... modifiers)
只要傳入TypeName(Class)、name(名稱)、Modifier(修飾符),就可以生成一個(gè)基本的成員變量。
成員變量一般來說由注解(Annotation)、修飾符(Modifier)、Javadoc(注釋)、initializer(實(shí)例化)。
注解
addAnnotation(TypeName name)
修飾符
addModifiers(Modifier ...modifier)
注釋
addJavadoc(String format, Object... args)
由于上述三個(gè)方法,都在通用方法介紹過這里就不再重復(fù)介紹。
實(shí)例化
initializer(String format, Object... args)
即成員變量的實(shí)例化,例:
public Activity mActivity = new Activity;
而 initializer方法中的內(nèi)容就是“=”后面的內(nèi)容 ,下面看下具體的代碼實(shí)現(xiàn),上面的成員變量:
ClassName activity = ClassName.get("android.app", "Activity"); FieldSpec spec = FieldSpec.builder(activity, "mActivity") .addModifiers(Modifier.PUBLIC) .initializer("new $T", activity) .build();
JavaPoet生成方法
JavaPoet生成方法分為兩種,第一種是構(gòu)造方法,另一種為常規(guī)的方法。
構(gòu)造方法
MethodSpec.constructorBuilder()
常規(guī)方法
MethodSpec.methodBuilder(String name)
方法的主要構(gòu)成有方法參數(shù)、注解、返回值、方法體、拋出異常五種,注解可以參考通用方法addAnnotation,其他方法我們將會(huì)一一介紹:
方法參數(shù)
addParameter(ParameterSpec parameterSpec)
設(shè)置方法參數(shù)的方法通過addParameterSpec來實(shí)現(xiàn),ParameterSpec的具體使用參考下一小節(jié)。
返回值
returns(TypeName returnType)
設(shè)置方法的返回值,只需傳入一個(gè)TypeName對(duì)象,而TypeName是ClassName,ParameterizedTypeName的基類。
方法體
在JavaPoet中,設(shè)置方法體內(nèi)容有兩個(gè)方法,分別是addCode和addStatement:
addCode() addStatement()
這兩個(gè)本質(zhì)上都是設(shè)置方法體內(nèi)容,但是不同的是使用addStatement()方法時(shí),你只需要專注于該段代碼的內(nèi)容,至于結(jié)尾的分號(hào)和換行它都會(huì)幫你做好。
而addCode()添加的方法體內(nèi)容就是一段無格式的代碼片,需要開發(fā)者自己添加其格式。
方法體模板
在JavaPoet中,設(shè)置方法體使用模板是比較常見的,因?yàn)閍ddCode和addStatement方法都存在這樣的一個(gè)重載:
addCode(String format, Object... args) addStatement(String format, Object... args)
在JavaPoet中,format中存在三種特定的占位符:
$T
$T 在JavaPoet代指的是TypeName,該模板主要將Class抽象出來,用傳入的TypeName指向的Class來代替。
ClassName bundle = ClassName.get("android.os", "Bundle"); addStatement("$T bundle = new $T()",bundle)
上述添加的代碼內(nèi)容為:
Bundle bundle = new Bundle();
$N
$N在JavaPoet中代指的是一個(gè)名稱,例如調(diào)用的方法名稱,變量名稱,這一類存在意思的名稱
addStatement("data.$N()",toString)
上述代碼添加的內(nèi)容:
data.toString();
$S
$S在JavaPoet中就和String.format中%s一樣,字符串的模板,將指定的字符串替換到$S的地方
.addStatement("super.$S(savedInstanceState)","onCreate")
即將"onCreate"字符串代替到$S的位置上.
拋出異常
.addException(TypeName name)
設(shè)置方法拋出異常,可以使用addException方法,傳入指定的異常的ClassName,即可為該方法設(shè)置其拋出該異常.
JavaPoet生成方法參數(shù)
JavaPoet生成有參方法時(shí),需要填充參數(shù),而生成參數(shù)則需要通過ParameterSpec這個(gè)類。
addParameter(ParameterSpec parameterSpec)
初始化ParameterSpec
ParameterSpec.builder(TypeName type, String name, Modifier... modifiers)
給參數(shù)設(shè)置其Class,以及參數(shù)名稱,和修飾符.
通常來說參數(shù)的構(gòu)成包括:參數(shù)的類型(Class)、參數(shù)的名稱(name)、修飾符(modifiers)、注解(Annotation)
除了builder方法初始化類型、以及名稱、修飾符之外,其余可以通過如下方法進(jìn)行設(shè)置:
添加修飾符
.addModifiers(Modifier modifier)
添加注解
addAnnotation(TypeName name)
添加修飾符、注解具體使用可參考通用方法。
JavaPoet生成注解
在JavaPoet創(chuàng)建類、成員變量、方法參數(shù)、方法,都會(huì)用到注解。
如果使用不包含屬性的注解可以直接通過
.addAnnotation(TypeName name)
直接傳入TypeName或者Class進(jìn)行設(shè)置。
如果使用的注解包含屬性,并且不止一個(gè)時(shí),這時(shí)候就需要生成AnnotationSpec來解決,下面簡單了解下AnnotationSpec。
初始化AnnotationSpec
AnnotationSpec.builder(ClassName type)
可以發(fā)現(xiàn)初始化,只需傳入ClassName或者Class即可。
設(shè)置屬性
addMember(String name, String format, Object... args)
使用addMember可以設(shè)置注解的屬性值,name對(duì)應(yīng)的就是屬性名稱,format的內(nèi)容即屬性體,同樣方法體的格式化在這里也是適用的。
JavaPoet如何生成代碼
如果上述內(nèi)容你已經(jīng)看完,那么恭喜你,你已經(jīng)明白JavaPoet的意圖,但是現(xiàn)在的你,還差最后一步,即如何生成代碼。
JavaPoet中負(fù)責(zé)生成的類是JavaFile
JavaFile.builder(String packageName, TypeSpec typeSpec)
JavaFile通過向build方法傳入PackageName(Java文件的包名)、TypeSpec(生成的內(nèi)容)生成。
打印結(jié)果
javaFile.writeTo(System.out)
生成的內(nèi)容會(huì)輸出到控制臺(tái)中
生成文件
javaFile.writeTo(File file)
生成的內(nèi)容會(huì)以java文件的方式,存放到你傳入File文件的位置
結(jié)束語
當(dāng)你讀完了本文,如果你產(chǎn)生下面的想法:
- JavaPoet原來還可以這樣
- JavaPoet編寫過程為什么那么流暢,原來Java文件也可以用編程的方式生成
- JavaPoet可不可以改進(jìn)我的編碼流程,提升效率
那么說明你已經(jīng)對(duì)JavaPoet感興趣了,可以自己動(dòng)手嘗試一下,感受下JavaPoet的魅力。
最后貼一張,JavaPoet秘籍,有了它會(huì)很好的幫助你使用JavaPoet.
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringCloud?hystrix斷路器與局部降級(jí)全面介紹
什么是服務(wù)降級(jí)?當(dāng)服務(wù)器壓力劇增的情況下,根據(jù)實(shí)際業(yè)務(wù)情況及流量,對(duì)一些服務(wù)和頁面有策略的不處理或換種簡單的方式處理,從而釋放服務(wù)器資源以保證核心交易正常運(yùn)作或高效運(yùn)作2022-10-10SpringMVC中RequestContextHolder獲取請求信息的方法
這篇文章主要介紹了SpringMVC中RequestContextHolder獲取請求信息的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Spring?Boot?整合JPA?數(shù)據(jù)模型關(guān)聯(lián)使用操作(一對(duì)一、一對(duì)多、多對(duì)多)
這篇文章主要介紹了Spring?Boot?整合JPA?數(shù)據(jù)模型關(guān)聯(lián)操作(一對(duì)一、一對(duì)多、多對(duì)多),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07基于spring boot 2和shiro實(shí)現(xiàn)身份驗(yàn)證案例
這篇文章主要介紹了基于spring boot 2和shiro實(shí)現(xiàn)身份驗(yàn)證案例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04java顯示當(dāng)前的系統(tǒng)時(shí)間
這篇文章主要介紹了java如何顯示當(dāng)前的系統(tǒng)時(shí)間,代碼很簡單,自己可以自定義顯示的系統(tǒng)時(shí)間的顏色和字體,需要的朋友可以參考下2015-10-10SpringMVC整合SSM實(shí)現(xiàn)異常處理器詳解
SpringMVC是一種基于Java,實(shí)現(xiàn)了Web MVC設(shè)計(jì)模式,請求驅(qū)動(dòng)類型的輕量級(jí)Web框架,即使用了MVC架構(gòu)模式的思想,將Web層進(jìn)行職責(zé)解耦?;谡埱篁?qū)動(dòng)指的就是使用請求-響應(yīng)模型,框架的目的就是幫助我們簡化開發(fā),SpringMVC也是要簡化我們?nèi)粘eb開發(fā)2022-10-10springboot+thymeleaf整合阿里云OOS對(duì)象存儲(chǔ)圖片的實(shí)現(xiàn)
本文主要介紹了springboot+thymeleaf整合阿里云OOS對(duì)象存儲(chǔ)圖片的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05