摘要:注解處理器初探平時做項(xiàng)目中有個非常好用的一個插件叫它提供了一些簡單的注解可以用來生成和一些方法提高了開發(fā)的效率節(jié)省了開發(fā)時間今天我們就來看看使用的什么方式來實(shí)現(xiàn)這種操作的其實(shí)使用的是這個是中增加的新功能像只是一個注解它真正的處理部分是在注解
注解處理器初探
????平時做項(xiàng)目中有個非常好用的一個插件,叫l(wèi)ombok.它提供了一些簡單的注解,可以用來生成javabean和一些getter/setter方法,提高了開發(fā)的效率節(jié)省了開發(fā)時間.
今天我們就來看看lombok使用的什么方式來實(shí)現(xiàn)這種操作的.其實(shí)lombok使用的是annotation processor,這個是jdk1.5中增加的新功能.像@Getter只是一個注解,它真正的處理部分
是在注解處理器里面實(shí)現(xiàn)的.官方參考鏈接.
????注解處理器其實(shí)全稱叫Pluggable Annotation Processing API,插入式注解處理器,它是對JSR269提案的實(shí)現(xiàn),具體可以看鏈接里面的內(nèi)容,JSR269鏈接.
它是怎么工作的呢?可以參考下圖:
1.parse and enter:解析和輸入,java編譯器這個階段會把源代碼解析生成AST(抽象語法分析樹)
2.annotation processing:注解處理器階段,此時將調(diào)用注解處理器,這時候可以校驗(yàn)代碼,生成新文件等等(處理完可以循環(huán)到第一步)
3.analyse and generate:分析和生成,此時前兩步完成后,生成字節(jié)碼(這個階段進(jìn)行了解糖,比如類型擦除)
這些其實(shí)只是為了給大家留有一個粗淺的印象,它是怎么執(zhí)行的.
????看了上面的資料,大腦中應(yīng)該有了一個大概的印象,現(xiàn)在我們實(shí)際操作一下寫一個簡單的例子,實(shí)踐一下.
要使用注解處理器需要兩個步驟:
1.自定義一個注解
2.繼承AbstractProcessor并且實(shí)現(xiàn)process方法
我們接下來寫一個很簡單的例子,就是在一個類上加上@InterfaceAnnotation,編譯的時候去生成一個"I"+類名的接口類.
首先我這里是定義了兩個moudle,一個用來寫注解和處理器,另一個用來調(diào)用注解.
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface InterfaceAnnotation { }
1.@Target:表示的是這個注解在什么上面使用,這里ElementType.TYPE是指在類上使用該注解
2.@Retention:表示的是保留到什么階段,這里RetentionPolicy.SOURCE是源代碼階段,編譯后的class上就沒有這個注解了
@SupportedAnnotationTypes(value = {"com.example.processor.InterfaceAnnotation"}) @SupportedSourceVersion(value = SourceVersion.RELEASE_8) public class InterfaceProcessor extends AbstractProcessor { @Override public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) { Messager messager = processingEnv.getMessager(); messager.printMessage(Diagnostic.Kind.NOTE, "進(jìn)入到InterfaceProcessor中了~~~"); // 將帶有InterfaceProcessor的類給找出來 Set extends Element> clazz = roundEnv.getElementsAnnotatedWith(InterfaceAnnotation.class); clazz.forEach(item -> { // 生成一個 I + 類名的接口類 String className = item.getSimpleName().toString(); className = "I" + className.substring(0, 1) + className.substring(1); TypeSpec typeSpec = TypeSpec.interfaceBuilder(className).addModifiers(Modifier.PUBLIC).build(); try { // 生成java文件 JavaFile.builder("com.example.processor", typeSpec).build().writeTo(new File("./src/main/java/")); } catch (IOException e) { e.printStackTrace(); } }); return true; } }
1.@SupportedAnnotationTypes:表示這個processor類要對什么注解生效
2.@SupportedSourceVersion:表示支持的java版本
3.annotations:被要求的注解,就是@SupportedAnnotationTypes對應(yīng)的注解
4.roundEnv:存放著當(dāng)前和上一輪processing的環(huán)境信息
5.TypeSpec這個可能有點(diǎn)沒看懂是干嘛的,它是javaPoet中的一個類,javaPoet是java用于生成java文件的一款第三方插件很好用,所以這里使用了這個類來生成java文件,
實(shí)際上這里用java自帶的PrintWriter等輸入輸出流也可以生成java文件,生成文件有很多方式.javaPoet的鏈接.javaPoet使用指南.
6.Messager是用來打印輸出信息的,System.out.println其實(shí)也可以;
7.process如果返回是true后續(xù)的注解處理器就不會再處理這個注解,如果是false,在下一輪processing中,其他注解處理器也會來處理改注解.
寫好之后,這里需要指定processor,META-INF/services/javax.annotation.processing.Processor 寫好com.example.processor.InterfaceProcessor.如果你不知道這是啥,可以看下我另一篇博客(實(shí)力推廣XD)什么是SPI
我們在把注解處理器給編譯好,maven里插件的設(shè)置:
org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 1.8 -proc:none
此時的目錄結(jié)構(gòu)是這樣:
. ├── HELP.md ├── pom.xml ├── processor.iml └── src └── main ├── java │?? └── com │?? └── example │?? └── processor │?? ├── InterfaceAnnotation.java │?? └── InterfaceProcessor.java └── resources └── META-INF └── services └── javax.annotation.processing.Processor
然后mvn clean install.
第三步:使用注解在使用之前呢,注解處理器要是編譯好的.引入注解處理器的jar包.
測試類加上@InterfaceAnnotation
@InterfaceAnnotation public class TestProcessor { }
maven指定編譯時使用的注解處理器.
org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 1.8 UTF-8 com.example.processor.InterfaceProcessor
此時目錄結(jié)構(gòu)是
. ├── HELP.md ├── pom.xml ├── src │?? └── main │?? ├── java │?? │?? └── com │?? │?? └── example │?? │?? └── test │?? │?? └── TestProcessor.java │?? └── resources └── test.iml
然后mvn compile,生成了java文件,此時目錄結(jié)構(gòu)是:
. ├── HELP.md ├── pom.xml ├── src │?? └── main │?? ├── java │?? │?? └── com │?? │?? └── example │?? │?? ├── processor │?? │?? │?? └── ITestProcessor.java // 這里就是生成的java文件 │?? │?? └── test │?? │?? └── TestProcessor.java │?? └── resources ├── target │?? ├── classes │?? │?? └── com │?? │?? └── example │?? │?? └── test │?? │?? └── TestProcessor.class │?? ├── generated-sources │?? │?? └── annotations │?? └── maven-status │?? └── maven-compiler-plugin │?? └── compile │?? └── default-compile │?? ├── createdFiles.lst │?? └── inputFiles.lst └── test.iml
看到了生成的java文件就大功告成~
總結(jié):1.java注解處理器在很多地方都可以使用,實(shí)際應(yīng)用比如lombok,安卓生成fragment等等,只使用一個注解可以省去很多代碼,提高效率;
2.本文只是列舉了一個很簡單的例子,很多注解處理器里面的api都沒有使用到,讀者有興趣的可以自行研究,而且有涉及到抽象語法樹的api;
3.注解處理器可以用于生成新的類來完成某些功能,但是不能直接修改當(dāng)前的類.
1.https://docs.oracle.com/javas...
2.https://jcp.org/aboutJava/com...
3.https://github.com/square/jav...
4.https://www.cnblogs.com/throw...
5.http://notatube.blogspot.com/...
6.https://www.baeldung.com/java...
7.http://hannesdorfmann.com/ann...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75347.html
摘要:虛擬主機(jī)管理系統(tǒng),是干嘛的虛擬主機(jī)管理系統(tǒng)是一款管理軟件,它可以實(shí)現(xiàn)對虛擬主機(jī),操作系統(tǒng)的服務(wù)器等進(jìn)行再次設(shè)置,一般來說是服務(wù)商用來管理域名,虛擬主機(jī),數(shù)據(jù)庫,還有企業(yè)郵箱等的一個網(wǎng)站平臺。同時虛擬主機(jī)管理系統(tǒng)還包含了財(cái)務(wù)管理功能功能。虛擬主機(jī)管理系統(tǒng),是干嘛的?虛擬主機(jī)管理系統(tǒng)是一款管理軟件,它可以實(shí)現(xiàn)對虛擬主機(jī),操作系統(tǒng)的服務(wù)器等進(jìn)行再次設(shè)置,一般來說是IDC服務(wù)商用來管理域名,虛擬主機(jī)...
摘要:同時虛擬主機(jī)管理系統(tǒng)還包含了財(cái)務(wù)管理功能功能。隨著互聯(lián)網(wǎng)的發(fā)展和技術(shù)的不斷更新,虛擬主機(jī)管理系統(tǒng)的開發(fā)也越來越完善,功能也越來越強(qiáng)大,尤其值得一說的是虛擬主機(jī)管理系統(tǒng)更加智能化。點(diǎn)開網(wǎng)頁出現(xiàn)虛擬主機(jī)已開通是什么意思?虛擬主機(jī)是把一臺服務(wù)器分成很多虛擬的服務(wù)器,每一個虛擬主機(jī)都具有獨(dú)立的域名和完整的Internet服務(wù)器(支持WWW、FTP、E-mail等)功能。缺點(diǎn)只有一個id,一旦有別的網(wǎng)...
摘要:先來看代碼吧,一會松哥再慢慢解釋關(guān)于這一段自動配置,解釋如下首先注解表明這是一個配置類。本文的案例,松哥已經(jīng)上傳到上了,地址。我們使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 為我們帶來了眾多的自動化配置,有了這些自動化配置,我們可以不費(fèi)吹灰之力就能搭建一個生產(chǎn)級開發(fā)環(huán)境,有的小伙伴會覺得這個 Starter 好神奇呀!其實(shí) Starter 也都...
摘要:為何有查閱了的文檔,并沒有找到字段的定義,直到才知道它是中最早就提出的概念。況且目前大部分仍是采用,所以便使用了另一個字段。所以目前主流的打包工具都是支持的,鑒于其優(yōu)點(diǎn),字段很有可能加入的規(guī)范之中。 引入 最近團(tuán)隊(duì)的一個同學(xué)在搞 npm library 源碼的調(diào)試插件,因?yàn)閮?nèi)部的一個組件庫含有大量的邏輯,在某個項(xiàng)目中不經(jīng)意就出現(xiàn)一個磨人的 bug,但是組件庫發(fā)布都是打包編譯后的代碼,而...
閱讀 1452·2021-09-23 11:21
閱讀 3140·2019-08-30 14:14
閱讀 3221·2019-08-30 13:56
閱讀 4181·2019-08-30 11:20
閱讀 1981·2019-08-29 17:23
閱讀 2801·2019-08-29 16:14
閱讀 1730·2019-08-28 18:18
閱讀 1512·2019-08-26 12:14