java retentionpolicy_Java注解之如何利用RetentionPolicy.SOURCE生存周期

上一篇文章簡單講了下Java注解的學習之元注解說明,學習了Java注解是如何定義的,怎么使用的,但是并沒有介紹Java的注解是怎么起作用的,像Spring Boot里面的那些注解,到底是怎么讓程序這樣子運行起來的?特別是講到RetentionPolicy這一塊,到底在SOURCE階段,在CLASS階段,在RUNTIME階段有什么差別,注解是如何在這三個階段起作用的呢?而且,在SOURCE階段,在CLASS階段,程序又不運行,那注解到底會用來做些什么呢?

帶著這些疑問,我就去了解下了如何讓注解起作用,發現RUNTIME階段的介紹到處都是,但是SOURCE和CLASS階段就很少文章講解到了,真的得搜刮好幾十篇文章才能成功的把程序跑起來,幾乎每一篇文章都少講了些東西。

本文優先講的是SOURCE階段注解如何發揮作用,發現這一塊涉及的知識非常多且難,資料還少,另外還發現,Java服務器端編程的人用這個反而不如Android開發的人用得多。對我學習SOURCE階段的注解幫助最大的是Pluggable Annotation Processing API,JSR269插件化注解API以及JVM進階 -- 淺談注解處理器。搜索這方面的資料用“插件化注解處理API”這個關鍵詞能搜得更全。

這幾篇文章基本上把SOURCE階段的注解實現和使用講了,但是具體細節,比如用javac直接編譯運行代碼,javac使用jar包,使用maven等三個方式如何運行注解處理器,倒是基本上蜻蜓點水,摸索了我好久才搞定了。關于注解處理器的知識,可以從如上三篇文章了解,本文主要講注解的定義和運行。

我用的代碼是摘抄至 JVM進階 -- 淺談注解處理器 ,它定義了一個CheckGetter的注解,用來檢查一個類里面的字段,哪個沒有Getter方法,沒有的話編譯就報錯。不過我的和他的稍稍不同,他的代碼定義沒有放到package里面,我的放到package里面了,這樣子的使用和執行又有了點不同。

首先,定義CheckGetter注解:

package com.shahuwang.processor;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.FIELD})

@Retention(RetentionPolicy.SOURCE)

public @interface CheckGetter {

}

注意上面的代碼,是放到 package com.shahuwang.processor 里面的,因此,先創建如下結構的文件夾

Processor

—— com

—— shuhuwang

—— processor

—— CheckGetter.java

注解已經定義好了,現在先來用一下這個注解:

package com.shahuwang.processor;

@CheckGetter

public class TestGetter {

String name;

String first;

public String getName(){

return this.name;

}

}

這個類有兩個字段,但是有一個字段沒有設置getter。

下面才是真正重要的代碼,就是讓CheckGetter這個注解真正能運行起來,發揮作用:

package com.shahuwang.processor;

import javax.annotation.processing.AbstractProcessor;

import javax.annotation.processing.RoundEnvironment;

import javax.annotation.processing.SupportedAnnotationTypes;

import javax.annotation.processing.SupportedSourceVersion;

import javax.lang.model.SourceVersion;

import javax.lang.model.element.ExecutableElement;

import javax.lang.model.element.Modifier;

import javax.lang.model.element.TypeElement;

import javax.lang.model.element.VariableElement;

import javax.lang.model.util.ElementFilter;

import javax.tools.Diagnostic;

import javax.lang.model.element.Element;

import java.util.Set;

// 這個地方換了包名就需要改過來,否則processor就不會執行了, 這里是最需要注意的地方,千萬注意!!!!!

@SupportedAnnotationTypes("com.shahuwang.processor.CheckGetter")

@SupportedSourceVersion(SourceVersion.RELEASE_11)

public class CheckGetterProcessor extends AbstractProcessor {

@Override

public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {

for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(CheckGetter.class))) {

for (VariableElement field : ElementFilter.fieldsIn(annotatedClass.getEnclosedElements())) {

if(!containsGetter(annotatedClass, field.getSimpleName().toString())){

processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,

String.format("getter not found for '%s.%s'.", annotatedClass.getSimpleName(), field.getSimpleName()));

}

}

}

return false;

}

private static boolean containsGetter(TypeElement typeElement, String name){

String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();

for(ExecutableElement executableElement: ElementFilter.methodsIn(typeElement.getEnclosedElements())){

if(!executableElement.getModifiers().contains(Modifier.STATIC) &&

executableElement.getSimpleName().toString().equals(getter) &&

executableElement.getParameters().isEmpty()){

return true;

}

}

return false;

}

}

上面這段代碼要理解的概念有點兒多,實際上我現在也不是很懂,但是本文的目標是先讓注解處理器跑起來,所以先不管。這里最重要也是折磨我最慘的地方,就是這一句@SupportedAnnotationTypes("com.shahuwang.processor.CheckGetter"),你定義的注解在哪個package下,這里就要寫完整了,如果寫錯了,注解處理器就不起作用了。

現在在Processor目錄下,打開命令行,先編譯CheckGetterProcessor.java: javac com/shahuwang/processor/CheckGetterProcessor.java,編譯好之后就可以使用了,再執行命令:javac -processor com.shahuwang.processor.CheckGetterProcessor com/shahuwang/processor/TestGetter.java,便可以看到這樣的提示:

錯誤: getter not found for 'TestGetter.first'.

上面這種方式,需要每次執行編譯的時候,指定一下processor才能做到檢查作用,那如果在團隊開發中,希望自動執行一些檢查,那可以用SPI 服務提供者發現機制或者maven來實現。

SPI 服務提供者發現機制就是配置META-INF文件夾和里面的文件,告訴Java你要執行某個東西,這個東西的路徑在哪里。再把編譯好的processor和META-INF打包成jar包,就可以很方便使用了。文件夾和文件結構如下:

processor

-com

-shahuwang

- processor

- CheckGetterProcessor.class

-META-INF

-services

- javax.annotation.processing.Processor

編譯方式和上述一樣。

javax.annotation.processing.Processor是一個普通的文本,就是告知java一些關于注解處理器的配置,里面的內容如下:

com.shahuwang.processor.CheckGetterProcessor

就是告知這個注解處理器要用哪些個,如果有多個的話,可以一行一個。

然后在processor目錄下,執行指令:jar -cvf processor.jar com META-INF, 形成了一個 processor.jar 的包,此時可以執行指令:

javac -cp processor.jar com/shahuwang/processor/TestGetter.java

就會自動執行注解處理器檢查字段有沒有getter方法了。

jar包的這個方法,其實是把注解和注解的實現單獨放一塊作為一個插件來使用了,maven也是如此的。

現實的開發中,還是用maven最多,先用指令創建一個maven項目:mvn archetype:generate -DgroupId=com.shahuwang -DartifactId=Processor -Dpackage=com.shahuwang.processor

然后在pom.xml的層級下添加如下配置:

UTF-8

UTF-8

1.8

1.8

1.8

org.apache.maven.plugins

maven-compiler-plugin

3.5.1

1.8

1.8

UTF-8

com.shahuwang.processor.CheckGetterProcessor

代碼目錄結構如下:

Processor

- src

- main

- java

-com

-shahuwang

-processor

-CheckGetter.java

-CheckGetterProcessor.java

- pom.xml

然后Processor目錄下執行: mvn clean install, 這個項目就會被安裝到本地的maven庫里面。

再用maven新建一個TestProcessor項目,項目結構如下:

TestProcessor

- src

- main

- java

-com

-shahuwang

-TestGetter.java

- pom.xml

TestGetter.java 的代碼上面有。

修改pom.xml, 先在 下添加:

UTF-8

UTF-8

1.8

1.8

1.8

org.apache.maven.plugins

maven-compiler-plugin

3.5.1

1.8

1.8

UTF-8

com.shahuwang.processor.CheckGetterProcessor

再在dependencies添加:

com.shahuwang

Processor

1.0-SNAPSHOT

也就是引入上面編譯好的處理器的包。

現在,在TestProcessor目錄下執行:

mvn compile

就會看到熟悉的提示:

錯誤: getter not found for 'TestGetter.first'.

三種主流的注解處理器使用方式現在都搞懂怎么使用了。下一篇文章將會關注注解處理器的使用方法,各個注解處理器API的使用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/529996.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529996.shtml
英文地址,請注明出處:http://en.pswp.cn/news/529996.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在java程序中定義的類有兩種成員_java試題 急需答案 謝謝!!!

三、填空(每小題2分,共10分)1.在Applet中,創建一個具有10行45列的多行文本區對象ta的語句為:2.創建一個標識有“關閉”字樣的標簽對象gb的語句為。3.方法是一種僅有方法頭,沒...三、填空(每小題…

java 同步 變量,在java中的對象上同步,然后更改同步的變量的值

I came across a code like thissynchronized(obj) {obj new Object();}Something does not feel right about this , I am unable to explain, Is this piece of code OK or there is something really wrong in it, please point it out.Thanks解決方案Its probably not wha…

java set泛型_Java 集合二 泛型、Set相關

泛型1、在定義一個類的方法時,因為不確定返回值類型,所以用一個符號代替,這個符號就是泛型eg:ArrayList list new ArrayList();2、泛型的好處:1、提高了數據的安全性,將運行時的問題提前暴露在編譯階段2、避免了強轉的…

java annotation 實現_在Java中如何實現自己的annotation

1. 先定義annotation2. 使用annotation例子:import java.lang.annotation.*;import java.lang.reflect.Method;Target(ElementType.METHOD)Retention(RetentionPolicy.RUNTIME)interface Test {String info() default "";}class Annotated {Test(info &q…

登錄界面攔截java_java攔截通過url訪問頁面,必須通過登錄頁面訪問目標頁面

在web.xml中配置過濾:LoginFiltercom.verification.action.LoginFilterLoginFiltery/form/dealParse.do/* 攔截所有請求/.do 攔截以“.do”結尾的請求/index.jsp 攔截指定的jsp/artery/form/* 攔截該目錄下的所有請求等等攔截器,攔截請求類&#xf…

python textwrap_[Python標準庫]textwrap——格式化文本段落

textwrap——格式化文本段落作用:通過調整換行符在段落中出現的位置來格式化文本。 Python 版本:2.5 及以后版本 需要美觀打印時,可以用 textwrap 模塊來格式化要輸出的文本。這個模塊允許通過編程提供類似段落自動換行或填充…

java 字符串 1_java 字符串操作大全1

1、length() 字符串的長度例:char chars[]{a,b.c};String snew String(chars);int lens.length();2、charAt() 截取一個字符例:char ch;ch"abc".charAt(1); 返回b3、getChars() 截取多個字符void getChars(int sourceStart,int sourceEnd,char…

java實現權限_Java實現權限管理的兩種方式

編輯特別推薦:種方式:利用filter、xml文件和用戶信息表配合使用來實現權限管理。1.過濾器filterpackage cn.com.aaa.bbb.filter;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.List…

java 輸入16進制_嘗試使用十六進制輸入來使用小端和大端

我試圖用這兩個原型編寫C函數:int extract_little (char* str, int ofset, int n);int extract_big(char* str, int ofset, int n);現在一般的想法是我需要從地址str ofset開始以兩種格式返回一個n字節整數 . 附: Ofset還沒有做任何事情,我計…

java gson_Java 中 Gson的使用

JSON 是一種文本形式的數據交換格式,它比XML更輕量、比二進制容易閱讀和編寫,調式也更加方便;解析和生成的方式很多,Java中最常用的類庫有:JSON-Java、Gson、Jackson、FastJson等一、Gson的基本用法Gson提供了fromJson() 和toJson…

spring注入普通java類_普通java類如何取得注入spring Ioc容器的對象

[除了使用XML配置外,還可以選擇使用基于注解(annotation)的配置方式,其依賴于字節碼來織入組件。注解注入在XML注入之前完成,因此在XML配置中可以重載注解注入的屬性。一、建一個SpringUtil類package com.ceopen.eoss.spring; import org.spr…

java web 集成dom4j_[JavaWeb基礎] 031.dom4j寫入xml的方法

上一篇我們講述了dom4j讀取xml的4種方法,甚是精彩,那么怎么樣寫入xml呢?我們直接看下源碼實現。public static void main(String[] args) throws Exception {// 創建文檔Document document DocumentHelper.createDocument();// 設置編碼docu…

java servlet 調試日志 logger sae_java servlet 調試日志 lo

java servlet 調試日志 lo[2021-02-10 08:32:08] 簡介:php去除nbsp的方法:首先創建一個PHP代碼示例文件;然后通過“preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/", " ", strip_tags($val));”方法去除所有nbsp即可。推薦&#x…

java接口權限管理在哪里_java訪問權限控制

為什么java要有訪問權限的控制?訪問權限的設置和代碼的重構有關。在一個項目中,大多數的時間和金錢都投入到了代碼的維護當中。維護中一定會修改已存在的不合理的代碼。但是在重構的過程中,就出現了這樣的問題:如何保證不影響那些使用了待修…

java8 stream index_Java8的stream用法整理

/***authorindex* date 2020/10/27**/public classTestcollectingAndThen {Testpublic voidtest(){final int NUM 14;List peopleList new ArrayList<>(NUM);String[] names {"小張", "小龍", "小牛", "小豬", "小黑&quo…

memo、 useMemo 和 useCallback語法講解

memo、 useMemo 和 useCallback 緩存組件, 對組件淺比較 (只有組件的props, (對函數,引用要用useCallback包裹)發生變化 緩存值, 依賴項變化&#xff0c;會從新計算。 緩存函數, 依賴項變化,重新生成新函數 useMemo 語法 對返回的值緩存進行優化 const memoizedValue useMem…

java只修改變的字段_java注解之運行時修改字段的注解值操作

今天遇到需求&#xff1a;導入Excel時候列頭會發生變化&#xff0c;客戶是大爺要求你改代碼&#xff0c;導入Excel是用easypoi做的&#xff0c;識別表頭是用注解Excel(name "xxx")通過這個name來匹配那你表頭要動&#xff0c;我這個注解是硬編碼所以就有動態設置這個…

求java簡單計算器源代碼_java簡單計算器源代碼

簡單計算器代碼package calcultorthree;import java.awt.BorderLayout;//導入邊界布局管理器類import java.awt.GridLayout;//導入網格布局管理器類import java.awt.TextField;//導入文本區域類import java.awt.event.ActionEvent;//導入事件類import java.awt.event.ActionLis…

java中間語言匯編語言_中間語言(IL) | 學步園

一、IL與匯編語言IL是微軟.NET平臺上衍生出的一門中間語言&#xff0c;.NET平臺上的各種高級語言(如C#&#xff0c;VB&#xff0c;F#)的編譯器會將各自的代碼轉化為IL。&#xff0c;其中包含了.NET平臺上的各種元素&#xff0c;如“范型”&#xff0c;“類”、、“接口”、“模…

java遍歷斐波納契數列_詳解循環、迭代、遞歸、分治(Leet Code 509 斐波那契數列),實際運用...

Multiple solutions of Fibonacci (Python or Java)本章是用英文寫的&#xff0c;作為或想成為一名優秀的攻城獅&#xff0c;習慣閱讀英文文檔將使你受益良多。例如更好的查看最新版的官方文檔、與國外友人交流、等等 其實英文的生詞也并不多,其中90&#xff05;的英文都在代碼…