JAVA基礎(chǔ)篇(6)-自定義注解(理論)

JAVA && Spring && SpringBoot2.x — 學(xué)習(xí)目錄

注解可以代替配置文件的功能蟆淀。

1. 元注解

元注解的作用就是注解其他注解赡译,一般我們使用自定義注解時(shí)腊徙,就需要用元注解來(lái)標(biāo)注我們自己的注解拦止,一共有以下四個(gè)元注解鸿脓。

1.1 @Target注解

說(shuō)明Annotation被修飾的范圍犹菇,可被用于packagestype(類闹蒜,接口寺枉,枚舉,Annotation類型)绷落、類型成員(方法姥闪,構(gòu)造方法,成員變量砌烁,枚舉值)筐喳、方法參數(shù)和本地變量(如循環(huán)變量,catch參數(shù))函喉。

一句話總結(jié):定義了注解的作用范圍避归。
使用方法:@Target(ElementType.TYPE)

類型 作用域
ElementType.CONSTRUCTOR 用于描述構(gòu)造器
ElementType.FIELD 用于描述域(類的成員)
ElementType.LOCAL_VARIABLE 用于描述局部變量(方法內(nèi)部變量)
ElementType.METHOD 用于描述方法
ElementType.PACKAGE 用于描述包
ElementType.PARAMETER 用于描述參數(shù)
ElementType.TYPE 用于描述類、接口(包括注解類型) 或enum聲明

1.2 @Retention

[瑞ten神]定義了該注解被保留的時(shí)間長(zhǎng)短管呵,有些只在源碼中保留梳毙,有些需要編譯成的class中保留,有些需要在程序運(yùn)行時(shí)候保留捐下。

一句話總結(jié):定義注解的聲明周期账锹。
使用方法:@Retention(RetentionPolicy.RUNTIME)

類型 作用域
RetentionPoicy.SOURCE 在源文件中有效(即源文件保留)
RetentionPoicy.CLASS 在class文件中有效(即class保留)
RetentionPoicy.RUNTIME 在運(yùn)行時(shí)有效(即運(yùn)行時(shí)保留)

1.3 Documented

標(biāo)記注解萌业,該元注解沒(méi)有屬性。表明這個(gè)注解應(yīng)該被javadoc工具記錄奸柬。即若使用javadoc之類的工具處理生年,該注解信息會(huì)被生成到文檔中。

1.4 Inherited

[in 和 瑞 ti 得]標(biāo)記注解廓奕,被他標(biāo)記的類型是可繼承的抱婉,比如一個(gè)class被@Inherited標(biāo)記,那么一個(gè)子類繼承該class后桌粉,則這個(gè)注解將被用于該class的子類授段。

自定義注解無(wú)@Inherited 自定義注解有@Inherited
子類能否繼承父類上的注解
子類方法,實(shí)現(xiàn)了父類的抽象方法番甩,能否可以繼承注解
子類方法,繼承了父類方法届搁,能否繼承注解
子類方法缘薛,覆蓋了父類方法,能否繼承注解
@MyAnno
public interface Eat {
}

class Parent implements Eat {

}

class Child implements Eat {

}

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@RequestMapping
@interface MyAnno {


}

class Test {

    public static void main(String[] args) {
        MyAnno eatAnnotation = Eat.class.getAnnotation(MyAnno.class);
        MyAnno parentAnnotation = Parent.class.getAnnotation(MyAnno.class);
        MyAnno childAnnotation = Child.class.getAnnotation(MyAnno.class);
        System.out.println(eatAnnotation);  //@com.galax.common.anno.customAnno.MyAnno()
        System.out.println(parentAnnotation); //null
        System.out.println(childAnnotation); //null
    }
}

我們的注解標(biāo)注了@Inherited表示該注解可以被繼承卡睦,但是parentAnnotation和childAnnotation依舊是null宴胧。需要注意:@Inherited繼承只能發(fā)生在類上,而不發(fā)生在接口上(也就是說(shuō)標(biāo)注在接口上依舊不能被繼承表锻。)

2. 自定義注解

1. 自定義注解的格式

public @interface 注解名 {定義體}

使用@interface定義的一個(gè)注解恕齐,自動(dòng)繼承了java.lang.annotation.Annotation接口,其中的每一個(gè)方法實(shí)際上是聲明了一個(gè)配置參數(shù)瞬逊。方法的名稱就是參數(shù)的名稱显歧,返回值就是參數(shù)的類型(返回值類型只能是:基本類型、Class确镊、String士骤、enum類型、Annotation類型蕾域,以及上述參數(shù)的數(shù)組類型)拷肌。可以使用default來(lái)聲明參數(shù)的默認(rèn)值。

2. 需要注意的點(diǎn):

  1. 只能用public或默認(rèn)(default)這兩個(gè)訪問(wèn)權(quán)修飾旨巷。
  2. 如果只有一個(gè)參數(shù)成員,最好把參數(shù)名稱設(shè)為"value"巨缘。
  3. 參數(shù)的返回值,只能是基本類型采呐,String類型若锁,Class類型,枚舉類型斧吐,注解類型以及他們的數(shù)組類型拴清。

3. 注解的默認(rèn)值

注解元素必須有確定的值靶病,要么是給定的默認(rèn)值,要是使用的時(shí)候賦予值口予。需要注意的是:若需要表達(dá)一個(gè)元素不存在值娄周,所以使用空字符串或者負(fù)數(shù)表示某個(gè)元素不存在,在定義注解時(shí)沪停,這已經(jīng)成為一個(gè)約定用法煤辨。

3. 如何獲取自定義注解信息

Java自定義注解是通過(guò)運(yùn)行時(shí)靠反射獲取注解

AnnotatedElement對(duì)象.png
Class上實(shí)現(xiàn)AnnotatedElement接口.png

Java的注解解析類主要是AnnotatedElement接口的實(shí)現(xiàn)類,我們可以通過(guò)反射獲取一個(gè)類的AnnotatedElement對(duì)象后木张,就可以通過(guò)下面表格的幾個(gè)方法众辨,訪問(wèn)Annotation信息。

方法返回值 方法 方式解釋
T getAnnotation(Class<T> annotationClass) 返回元素上存在的舷礼,指定類型的注解鹃彻。如果該類型注解不存在,則返回null妻献。
Annotation[] getAnnotations() 返回該元素上的所有注解蛛株。
T getDeclaredAnnotation(Class<T> annotationClass) 返回元素上存在,指定類型的注解育拨,忽略繼承注解谨履,如果該類型注解不存在,則返回null熬丧。
Annotation[] getDeclaredAnnotations() 返回直接存在于類上的所有注解笋粟,忽略繼承注解,如果該元素上沒(méi)有任何注解析蝴,那么將返回一個(gè)長(zhǎng)度為0的數(shù)組害捕。
boolean isAnnotationPresent(Class<? extends Annotation>) 判斷程序元素上是否包含指定類型的注解,存在則返回true闷畸,否則返回false吨艇。

1. 自定義注解:定義

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodInfo {
    String author() default "xioapang";
    String date();
    int revision() default 1;
    String comments();
}

2. 自定義注解:使用

public class AnnotationExample {
    @MethodInfo(author = "XXX", comments = "toString method", date = "Nov 17 2019", revision = 2)
    public String toString() {
        return "Overriden toString method";
    }
}

3. 自定義注解:解析

@Slf4j
public class AnnotationParsing {
    public static void main(String[] args) {
        try {
            //加載某個(gè)類上的所有方法
            for (Method method : AnnotationParsing.class.getClassLoader().loadClass("com.galax.common.anno.customAnno.AnnotationExample").getMethods()) {
                //判斷方法是否存在MethodInfo.class注解
                if (method.isAnnotationPresent(MethodInfo.class)) {
                    //獲取非繼承關(guān)系的所有注解
                    for (Annotation anno : method.getDeclaredAnnotations()) {
                        log.info("注解信息:{} ", anno);
                    }
                    //獲取元素上該注解的詳細(xì)信息
                    MethodInfo methodAnnotation = method.getAnnotation(MethodInfo.class);
                    log.info("版本號(hào):{}", methodAnnotation.revision());
                    log.info("作者:{}", methodAnnotation.author());
                    log.info("時(shí)間:{}", methodAnnotation.date());
                    log.info("描述:{}", methodAnnotation.comments());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

文章參考

深入理解Java自定義注解(一):入門(mén)

深入理解Java自定義注解(二)-使用自定義注解

Java反射獲取類和對(duì)象信息全解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腾啥,隨后出現(xiàn)的幾起案子东涡,更是在濱河造成了極大的恐慌,老刑警劉巖倘待,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疮跑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡凸舵,警方通過(guò)查閱死者的電腦和手機(jī)祖娘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啊奄,“玉大人渐苏,你說(shuō)我怎么就攤上這事掀潮。” “怎么了琼富?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵仪吧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鞠眉,道長(zhǎng)薯鼠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任械蹋,我火速辦了婚禮出皇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哗戈。我一直安慰自己郊艘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布唯咬。 她就那樣靜靜地躺著纱注,像睡著了一般。 火紅的嫁衣襯著肌膚如雪副渴。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天全度,我揣著相機(jī)與錄音煮剧,去河邊找鬼。 笑死将鸵,一個(gè)胖子當(dāng)著我的面吹牛勉盅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播顶掉,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼草娜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了痒筒?” 一聲冷哼從身側(cè)響起宰闰,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎簿透,沒(méi)想到半個(gè)月后移袍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡老充,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年葡盗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啡浊。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡觅够,死狀恐怖胶背,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喘先,我是刑警寧澤钳吟,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站苹祟,受9級(jí)特大地震影響砸抛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜树枫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一直焙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧砂轻,春花似錦奔誓、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至庄呈,卻和暖如春蜕煌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诬留。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工斜纪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人文兑。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓盒刚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親绿贞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子因块,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容