国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從APT中獲取運行時類信息

levinit / 2345人閱讀

摘要:概述從開始提供了一個新的被稱為的工具,使用其提供的我們可以通過類似數(shù)據(jù)結(jié)構(gòu)的方式來訪問被編譯的的源代碼。例如我們定義了一個注解該注解接受一個的參數(shù),注意該注解僅可見于源代碼編譯過程。

概述

從JDK1.6開始提供了一個新的被稱為APT(Annotation Processing Tool)的工具,使用其提供的APT我們可以通過類似數(shù)據(jù)結(jié)構(gòu)的方式來訪問被編譯的Java的源代碼。

利用這個新的工具提供的API我們可以在編譯Java源代碼的同時對現(xiàn)有代碼進行增強和生成代碼,比之以往通過運行時的反射以及通過Java的動態(tài)代理或者運行時字節(jié)碼修改來增強要來的更簡單并且運行時的效率要更高(指啟動時間)

問題描述

在Java程序運行時可以通過反射來獲取類的Meta信息,但是在APT中處理的是Java源代碼,此時無法直接獲取定義在Annotation里面的類型信息,因為沒有反射API可以使用。
例如我們定義了一個注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Service {

    Class[] value();
}

該注解接受一個Class的參數(shù),注意該注解僅可見于源代碼編譯過程。

如果想在APT中獲取Service.value,下面代碼是不可行的:

...
Service service = ...
Class[] cls = service.value();
...

運行這段代碼會在編譯時拋出異常,因為在編譯時類型信息無法直接獲取,只有Native數(shù)據(jù)和String可以直接獲取。

解決方案

如何解決該問題呢?我們需要使用APT提供的*Mirror API獲取Class的相關(guān)信息。

獲取AnnotationMirror對象

首先獲取AnnotationMirror對象:

AnnotationMirror svcAnnoMirror =
  MoreElements.getAnnotationMirror(classElement, Service.class).get();

MoreElements是Google Auto庫里面的一個工具類,getAnnotationMirror方法比較簡單,它返回Service Annotation對應(yīng)的AnnotationMirror對象。

上面的classElement是一個javax.lang.model.element.Element實例,在這里它代表了申明了Service這個Annotation的類的元素。

在APT里面,Java源代碼會被解釋稱類似XML的結(jié)構(gòu),比如類,字段,方法,方法的參數(shù)等都會被解釋稱一個元素,每個元素都是Element的實例

獲取Annotation定義的元素列表

然后獲取該Annotation里面定義的所有元素的列表:

Set elementSet = svcAnnoMirror.getElementValues().entrySet();

過濾出key是value的那個元素

if (entry.getKey().getSimpleName().toString().equals("value")) {
  AnnotationValues annoValue = entry.getValue();
}
獲取TypeElement

有了AnnotationValue,我們就可以取得內(nèi)部的值:

List values = (List) annoValue.getValue();

因為我們定義了Service.value是一個Class數(shù)組,所以這里我們需要把返回值強制轉(zhuǎn)換成List。

為了獲取Service.value里面定義的Class信息,我們需要使用TypeMirror API

DeclaredType declaredType = (DeclaredType) value.getValue();
TypeElement typeElement = (TypeElement) declaredType.asElement();

有了TypeElement,我們就可以訪問該類型相關(guān)的信息了,比如獲取其完整類名:

typeElement.getQualifiedName().toString();

當(dāng)然獲取它的實現(xiàn)的接口或者定義在它內(nèi)部的方法或者字段都是可以的。

完整代碼
AnnotationMirror svcAnnoMirror =
    MoreElements.getAnnotationMirror(classElement, Service.class).get();
List types = new ArrayList<>();
Observable.from(svcAnnoMirror.getElementValues().entrySet())
      .filter(entry -> "value".equals(entry.getKey().getSimpleName().toString()))
      .map(Map.Entry::getValue)
      .flatMap(annoValue -> Observable.from((List) annoValue.getValue()))
      .map(annoValue -> (DeclaredType) annoValue.getValue())
      .map(declaredType -> (TypeElement) declaredType.asElement())
      .map(typeElem -> typeElem.getQualifiedName().toString())
      .subscribe(types::add, logger::error);

上面代碼使用rxJava以及Lambda表達(dá)式來簡化代碼。

參見我的項目源碼:這里

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/65799.html

相關(guān)文章

  • 四大組件以及Application和Context的全面理解

    摘要:關(guān)于后稱的操作我們知道其實就是文件,所以這里的操作有獲取移動刪除。操作啟動停止重啟綁定解綁獲取系統(tǒng)服務(wù)以及多用戶操作。權(quán)限操作檢查本是否有某種權(quán)限檢查某是否有某種權(quán)限檢查權(quán)限授予權(quán)限等等。 先放一張圖吧 showImg(https://segmentfault.com/img/remote/1460000015839908); 2.用處 1.Context的實現(xiàn)類有很多,但是Cont...

    William_Sang 評論0 收藏0
  • 記一次Docker構(gòu)建失敗

    摘要:之所以在本地構(gòu)建,而沒有使用倉庫的,是因為,我們的鏡像采用了國內(nèi)阿里云的源,再加上某些很奇妙的網(wǎng)絡(luò)因素,在中自動構(gòu)建時,升級總會失敗。然而,在本地再次構(gòu)建成功。 見字如晤。 前段時間,Node.js 官方發(fā)布了Node 8.9.3 LTS版本,并且官網(wǎng)首頁提示新版本有重要安全更新,Important security releases, please update now! ,然后我立...

    joyqi 評論0 收藏0
  • 關(guān)于Apt注解實踐與總結(jié)【包含20篇博客】

    摘要:使用實現(xiàn)功能運行期注解案例使用簡單的注解,便可以設(shè)置布局,等效于使用實現(xiàn)路由綜合型案例比較全面的介紹從零起步,一步一步封裝簡易的路由開源庫。申明注解用的就是。返回值表示這個注解里可以存放什么類型值。 YCApt關(guān)于apt方案實踐與總結(jié) 目錄介紹 00.注解系列博客匯總 01.什么是apt 02.annotationProcessor和apt區(qū)別 03.項目目錄結(jié)構(gòu) 04.該案例作用 ...

    gnehc 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<