摘要:注解處理器初探平時做項目中有個非常好用的一個插件叫它提供了一些簡單的注解可以用來生成和一些方法提高了開發的效率節省了開發時間今天我們就來看看使用的什么方式來實現這種操作的其實使用的是這個是中增加的新功能像只是一個注解它真正的處理部分是在注解
注解處理器初探
????平時做項目中有個非常好用的一個插件,叫lombok.它提供了一些簡單的注解,可以用來生成javabean和一些getter/setter方法,提高了開發的效率節省了開發時間.
今天我們就來看看lombok使用的什么方式來實現這種操作的.其實lombok使用的是annotation processor,這個是jdk1.5中增加的新功能.像@Getter只是一個注解,它真正的處理部分
是在注解處理器里面實現的.官方參考鏈接.
????注解處理器其實全稱叫Pluggable Annotation Processing API,插入式注解處理器,它是對JSR269提案的實現,具體可以看鏈接里面的內容,JSR269鏈接.
它是怎么工作的呢?可以參考下圖:
1.parse and enter:解析和輸入,java編譯器這個階段會把源代碼解析生成AST(抽象語法分析樹)
2.annotation processing:注解處理器階段,此時將調用注解處理器,這時候可以校驗代碼,生成新文件等等(處理完可以循環到第一步)
3.analyse and generate:分析和生成,此時前兩步完成后,生成字節碼(這個階段進行了解糖,比如類型擦除)
這些其實只是為了給大家留有一個粗淺的印象,它是怎么執行的.
????看了上面的資料,大腦中應該有了一個大概的印象,現在我們實際操作一下寫一個簡單的例子,實踐一下.
要使用注解處理器需要兩個步驟:
1.自定義一個注解
2.繼承AbstractProcessor并且實現process方法
我們接下來寫一個很簡單的例子,就是在一個類上加上@InterfaceAnnotation,編譯的時候去生成一個"I"+類名的接口類.
首先我這里是定義了兩個moudle,一個用來寫注解和處理器,另一個用來調用注解.
@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, "進入到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對應的注解
4.roundEnv:存放著當前和上一輪processing的環境信息
5.TypeSpec這個可能有點沒看懂是干嘛的,它是javaPoet中的一個類,javaPoet是java用于生成java文件的一款第三方插件很好用,所以這里使用了這個類來生成java文件,
實際上這里用java自帶的PrintWriter等輸入輸出流也可以生成java文件,生成文件有很多方式.javaPoet的鏈接.javaPoet使用指南.
6.Messager是用來打印輸出信息的,System.out.println其實也可以;
7.process如果返回是true后續的注解處理器就不會再處理這個注解,如果是false,在下一輪processing中,其他注解處理器也會來處理改注解.
寫好之后,這里需要指定processor,META-INF/services/javax.annotation.processing.Processor 寫好com.example.processor.InterfaceProcessor.如果你不知道這是啥,可以看下我另一篇博客(實力推廣XD)什么是SPI
我們在把注解處理器給編譯好,maven里插件的設置:
org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 -proc:none
此時的目錄結構是這樣:
. ├── 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 UTF-8 com.example.processor.InterfaceProcessor
此時目錄結構是
. ├── HELP.md ├── pom.xml ├── src │?? └── main │?? ├── java │?? │?? └── com │?? │?? └── example │?? │?? └── test │?? │?? └── TestProcessor.java │?? └── resources └── test.iml
然后mvn compile,生成了java文件,此時目錄結構是:
. ├── 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文件就大功告成~
總結:1.java注解處理器在很多地方都可以使用,實際應用比如lombok,安卓生成fragment等等,只使用一個注解可以省去很多代碼,提高效率;
2.本文只是列舉了一個很簡單的例子,很多注解處理器里面的api都沒有使用到,讀者有興趣的可以自行研究,而且有涉及到抽象語法樹的api;
3.注解處理器可以用于生成新的類來完成某些功能,但是不能直接修改當前的類.
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...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75347.html
摘要:虛擬主機管理系統,是干嘛的虛擬主機管理系統是一款管理軟件,它可以實現對虛擬主機,操作系統的服務器等進行再次設置,一般來說是服務商用來管理域名,虛擬主機,數據庫,還有企業郵箱等的一個網站平臺。同時虛擬主機管理系統還包含了財務管理功能功能。虛擬主機管理系統,是干嘛的?虛擬主機管理系統是一款管理軟件,它可以實現對虛擬主機,操作系統的服務器等進行再次設置,一般來說是IDC服務商用來管理域名,虛擬主機...
摘要:同時虛擬主機管理系統還包含了財務管理功能功能。隨著互聯網的發展和技術的不斷更新,虛擬主機管理系統的開發也越來越完善,功能也越來越強大,尤其值得一說的是虛擬主機管理系統更加智能化。點開網頁出現虛擬主機已開通是什么意思?虛擬主機是把一臺服務器分成很多虛擬的服務器,每一個虛擬主機都具有獨立的域名和完整的Internet服務器(支持WWW、FTP、E-mail等)功能。缺點只有一個id,一旦有別的網...
摘要:先來看代碼吧,一會松哥再慢慢解釋關于這一段自動配置,解釋如下首先注解表明這是一個配置類。本文的案例,松哥已經上傳到上了,地址。我們使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中。Starter 為我們帶來了眾多的自動化配置,有了這些自動化配置,我們可以不費吹灰之力就能搭建一個生產級開發環境,有的小伙伴會覺得這個 Starter 好神奇呀!其實 Starter 也都...
摘要:為何有查閱了的文檔,并沒有找到字段的定義,直到才知道它是中最早就提出的概念。況且目前大部分仍是采用,所以便使用了另一個字段。所以目前主流的打包工具都是支持的,鑒于其優點,字段很有可能加入的規范之中。 引入 最近團隊的一個同學在搞 npm library 源碼的調試插件,因為內部的一個組件庫含有大量的邏輯,在某個項目中不經意就出現一個磨人的 bug,但是組件庫發布都是打包編譯后的代碼,而...
閱讀 1425·2021-09-23 11:21
閱讀 3123·2019-08-30 14:14
閱讀 3205·2019-08-30 13:56
閱讀 4158·2019-08-30 11:20
閱讀 1963·2019-08-29 17:23
閱讀 2780·2019-08-29 16:14
閱讀 1709·2019-08-28 18:18
閱讀 1501·2019-08-26 12:14