java 自定义注解_Java注解
前言
近日在閱讀開源項目,發(fā)現(xiàn)項目里好多奇奇怪怪的注解(@DataScope、@Log...)看得我一臉懵,不知道大家是否也有過這樣的經(jīng)歷,回想了一下,發(fā)現(xiàn)自己對于注解的知識,好像只停留在@Override。。。異常尷尬,所以今天就補補注解這個知識,并把自己的收獲記錄在此,與大家一同交流,如有不對的地方,敬請指正!
希望本文能給讀者帶來以下收獲:
·明白注解是什么,大概有什么用
·能理解別人代碼里面注解的作用
·能使用自定義注解
一、什么是注解
想要了解某個知識點,我首先推薦的都是去官網(wǎng)查看,下面看看Java官方對注解的解釋:
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
注解是元數(shù)據(jù)的一種形式,它提供有關(guān)程序的數(shù)據(jù),但這些數(shù)據(jù)不是程序本身的一部分。注解對它們注釋的代碼的操作沒有直接影響。
一堆英文讀完,一陣云里霧里。沒關(guān)系,這是正常操作,不過我們從翻譯中還是可以了解到注解可以提供數(shù)據(jù),并且數(shù)據(jù)是獨立于程序的,那么我們大致可以推斷出,注解其實是介于程序和數(shù)據(jù)之間的一種媒介,程序和數(shù)據(jù)通過注解達成了某種聯(lián)系,即注解類似一根紅線,把數(shù)據(jù)和程序關(guān)聯(lián)在一起。
二、從@Override開始
通過對Java官方提供的注解解釋的翻譯,我們篩選推斷出了一個關(guān)鍵信息——關(guān)聯(lián)。那到底如何理解這個詞呢?別急,我們從最熟悉的陌生人@Override開始,最熟悉是因為我們知道這是方法重寫,子類覆蓋父類方法用到的注解,陌生是因為我們從來沒有點進去了解過這個注解,那接下來就進去看看吧!
?import java.lang.annotation.*;?@Target(ElementType.METHOD)?@Retention(RetentionPolicy.SOURCE)?public @interface Override {?}短短的5行,好像除了第一行,其他啥都不知道。。。不急,我們一行一行來解讀!
·注解導(dǎo)入了一個annotation包
·注解的“套娃”行為@Target(ElementType.METHOD)、@Retention(RetentionPolicy.SOURCE)
·不同于接口和類的聲明public @interface Override { }
除了對新注解不認識,我們大致可以了解到注解的定義格式,修飾符 @interface 注解名{}。(有點接口的感覺)
三、禁止套娃——元注解
通過對@Override的剖析,我們了解了注解的定義格式,不過我們發(fā)現(xiàn)注解里面又有新的注解,本著刨根問底的好奇心,我們繼續(xù)進入@Target注解一探究竟!
?@Documented?@Retention(RetentionPolicy.RUNTIME)?@Target(ElementType.ANNOTATION_TYPE)?public @interface Target {? ? ?ElementType[] value();?}一直點擊,發(fā)現(xiàn)始終在@Documented、@Retention、@Target這幾個注解之間套娃,通過Java文檔我們了解到原來這些修飾注解的注解叫做元注解。元注解(meta-annotation)在java.lang.annotation包下:
@Retention
表示如何存儲被標記的注解(指定存儲級別),有以下三個級別
·RetentionPolicy.SOURCE:只保留到源碼級別,在編譯階段會被忽略,所以他們不會被寫入字節(jié)碼。
·RetentionPolicy.CLASS:(默認)編譯級別,在編譯時由編譯器保留,但被Java虛擬機(JVM)忽略。
·RetentionPolicy.RUNTIME:由JVM保留,可以在運行時環(huán)境使用。
@Target
表示被標記的注解可以用于哪種java元素(類、接口、屬性、方法......),有以下八種
@Documented
無論何時使用指定的注解,都應(yīng)使用Javadoc工具記錄這些元素。(即會在生成的javadoc中加入注解說明)
@Inherited
可以從超類繼承注釋類型,僅用于類的聲明(接口不會繼承)
@Repeatable
在Java SE 8中引入的,表示標記的注釋可以多次應(yīng)用于相同的聲明或類型使用。
四、注解的分類
通過對元注解的了解,我明白了一個注解都是由這些元注解修飾而來,而且我們也收獲了一個重要信息——注解可以修飾注解
這樣無限的套娃,就會有各種各樣的注解,那么到底有哪些注解呢?常見的注解大致分為以下四類:
元注解
即上文提及的5個元注解
jdk注解
常見的如
@Override @Deprecated @SuppressWarnings @SafeVarargs @FunctionalInterface
第三方注解
即第三方框架提供的注解,例如自動注入依賴@Autowired、@Controller等
自定義注解
即開發(fā)人員根據(jù)項目需求自定義的注解,用于一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。
實戰(zhàn)——定義自己的注解
看過了Java提供的注解,相信你已經(jīng)對注解有個大致的了解了。那你有沒有想過,注解是如何化腐朽為神奇,加了一個簡單的@Autowired就能實現(xiàn)依賴注入、@Setter就能實現(xiàn)set方法的生成,下面通過簡單的實戰(zhàn)來體會一下注解的神奇之處吧!
實戰(zhàn)目標:
使用自定義注解,通過在實體類及其屬性上加注解,實現(xiàn)對實體類查詢sql語句的構(gòu)造
ps:類似select * from t_user where t_name='kingwan'的形式
自定義注解的編寫規(guī)則
在開始實戰(zhàn)之前,我們先了解一下編寫自定義注解的規(guī)則:
·注解的定義為@interface,所有的注解會自動繼承java.lang.Annotation這個接口,并且不能再去繼承別的類或者接口
·參數(shù)成員只能用public或default(默認)訪問權(quán)限符修飾
·參數(shù)成員只能用八大基本數(shù)據(jù)類型、String、Enum、Class、annotations等數(shù)據(jù)類型,以及這些類型的數(shù)組
·要獲取類方法和字段的注解信息,必須通過java反射機制來獲取
·注解也可以沒有定義成員(只起到標識作用)
了解了注解的定義規(guī)范,接下來我們開始進入正式的實戰(zhàn)環(huán)節(jié)。
1.自定義注解@KingwanTable、KingwanColumn
對于實體類查詢的sql語句,我們需要知道兩個信息:①查詢的表名②字段名。并且我們通常習慣將用戶表t_user對應(yīng)于實體類User,那么我們?nèi)绾魏桶裻_user和User進行關(guān)聯(lián)呢?一想到關(guān)聯(lián),回顧我們最開始從官方文檔中提取出來的信息,沒錯,就是使用注解關(guān)聯(lián)。接下來定義兩個自定義注解:
·@KingwanTable:注解實體類對應(yīng)的表名
@Target(ElementType.TYPE)//作用在類/接口上?@Retention(RetentionPolicy.RUNTIME)//保留作用域:保留到運行時?public @interface KingwanTable {? ? ?String value();//參數(shù):表名?}·@KingwanColumn:注解實體類屬性對應(yīng)的表字段名
@Target(ElementType.FIELD)//表示作用在字段上?@Retention(RetentionPolicy.RUNTIME)//保留到運行時?public @interface KingwanColumn {? ? String value();//參數(shù):字段名?}2.實體類添加上自定義注解
有了自定義的兩個注解,那么我們現(xiàn)在就可以把它們加在實體類上。
·以下代碼定義了一個Student實體類,加上了@KingwanTable("t_student")映射表名,
·以下代碼創(chuàng)建了一個student對象,并初始化信息
3.反射獲取注解信息
有了一個加了自定義注解的Student實體類,那么我們想要構(gòu)造SQL,就有以下思路:
獲取到注解的信息(獲取表名、字段名)=>獲取屬性的值(字段值)=>構(gòu)造SQL
如何獲取呢?規(guī)則里說了,使用反射。
以下代碼通過獲取student的class對象,獲取類上的注解@KingwanTable信息。
aClass.isAnnotationPresent:判斷指定的注解是否存在
此時SQL打印的結(jié)果:
獲取到了類上的注解信息,接下來我們來看看如何獲取屬性上的注解信息
此時SQL的結(jié)果:
當然,如果有小伙伴跟著本文敲,可能在這一步就走不下去了,這是因為我們的get方法返回的字段類型多種多樣,所以僅僅invoke instanceof String是不夠的,我們還需要考慮其他情況(Integer、Date),限于篇幅原因,這里不做過多介紹,大家完全可以自行補充,如果想了解我的實現(xiàn)思路,移步:案例源碼地址
這樣,是不是就達到了我們要的效果了,對于任意簡單實體類,我們都可以通過加上該注解實現(xiàn)一個簡單的查找SQL的生成
你學廢了嗎!
總結(jié)
相信大家看我之后可能會有疑問,注解好復(fù)雜,費一大堆功夫,還不如直接點呢!的確,我最開始也覺得注解有點雞肋,不過用久了之后,發(fā)現(xiàn)真香!而且注解的作用不僅僅這些,本文的目的是讓大家對注解有一個簡單的了解,當你看到別人寫的注解是多么巧妙時,你也許就會發(fā)現(xiàn),原來注解這么好用!
·在編譯時進行格式檢查。如@Override
·跟蹤代碼依賴性,實現(xiàn)替代配置文件功能。通過處理注解信息生成代碼、XML文件。
·一些注釋可以在運行時進行檢查
結(jié)尾一張圖
一張思維導(dǎo)圖總結(jié)一下內(nèi)容,保存下來,時常復(fù)習!
總結(jié)
以上是生活随笔為你收集整理的java 自定义注解_Java注解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 白蚁“大军”夜袭上海!刘畊宏边直播边打:
- 下一篇: servlet 返回可访问文件_Java