什么是注解?
當(dāng)我們開發(fā)SpringBoot項(xiàng)目,我們只需對(duì)啟動(dòng)類加上@SpringBootApplication
,就能自動(dòng)裝配,不需要編寫冗余的xml配置。當(dāng)我們?yōu)轫?xiàng)目添加lombok依賴,使用@Data
來修飾實(shí)體類,我們就不需要編寫getter和setter方法,構(gòu)造函數(shù)
等等。@SpringBootApplication,@Data等
像這種以**"@"**
開頭的代碼 就是 注解, 只需簡簡單單幾個(gè)注解,就能幫助我們省略大量冗余的代碼,這是一個(gè)非常不可思議的事情!
但我們往往知道在哪些地方加上合適的注解,不然IDE會(huì)報(bào)錯(cuò),卻不知道其中的原理,那究竟什么是注解呢?
注解(Annotation ), 是 Java5 開始引入的新特性,是放在Java源碼的類、方法、字段、參數(shù)前的一種特殊“注釋”, 是一種標(biāo)記、標(biāo)簽。 注釋往往會(huì)被編譯器直接忽略,能夠被編譯器打包進(jìn)入class文件,并執(zhí)行相應(yīng)的處理。
按照慣例我們?nèi)タ聪伦⒔獾脑创a:
先新建一個(gè)注解文件:MyAnnotation.java
public @interface MyAnnotation {
}
發(fā)現(xiàn)MyAnnotation 是被@interface
修飾的,感覺和接口interface
很像。
我們?cè)偻ㄟ^idea來看下其的類繼承:
MyAnnotation 是繼承Annotation接口的。
我們?cè)俜淳幾g一下:
$ javac MyAnnotation.java
$ javap -c MyAnnotation
Compiled from "MyAnnotation.java"
public interface com.zj.ideaprojects.test3.MyAnnotation extends java.lang.annotation.Annotation {
}
發(fā)現(xiàn)生成的字節(jié)碼中 @interface變成了interface,MyAnnotation而且自動(dòng)繼承了Annotation
我們由此可以明白:注解本質(zhì)是一個(gè)繼承了Annotation 的特殊接口, 所以注解也叫聲明式接口
注解的分類
一般常用的注解可以分為三大類:
Java自帶的標(biāo)準(zhǔn)注解
例如:
元注解
元注解是能夠用于定義注解的注解, 或者說元注解是一種基本注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等
元注解也是Java自帶的標(biāo)準(zhǔn)注解,只不過用于修飾注解
,比較特殊。
@Retention
注解的保留策略, @Retention 定義了Annotation的生命周期 。當(dāng) @Retention 應(yīng)用到一個(gè)注解上的時(shí)候,它解釋說明了這個(gè)注解的的存活時(shí)間。
它的參數(shù):
RetentionPolicy.SOURCE | 注解只在源碼階段保留,在編譯器進(jìn)行編譯時(shí)它將被丟掉 |
---|---|
RetentionPolicy.CLASS | 注解只被保留到編譯進(jìn)行的時(shí)候,它并不會(huì)被加載到 JVM 中 |
RetentionPolicy.RUNTIME | 注解可以保留到程序運(yùn)行中的時(shí)候,它會(huì)被加載進(jìn) JVM中,在程序運(yùn)行中也可以獲取到它們 |
如果@Retention不存在,則該Annotation默認(rèn)為RetentionPolicy.CLASS
示例:
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
我們自定義的TestAnnotation 可以在程序運(yùn)行中被獲取到
@Documented
它的作用是 用于 制作文檔 ,將注解中的元素包含到 doc 中
一般不怎么用到,了解即可
@Target
@Target 指定了注解可以修飾哪些地方 , 比如方法、成員變量、還是包等等
當(dāng)一個(gè)注解被 @Target 注解時(shí),這個(gè)注解就被限定了運(yùn)用的場(chǎng)景。
常用的參數(shù)如下:
ElementType.ANNOTATION_TYPE | 給一個(gè)注解進(jìn)行注解 |
---|---|
ElementType.CONSTRUCTOR | 給構(gòu)造方法進(jìn)行注解 |
ElementType.FIELD | 給屬性進(jìn)行注解 |
ElementType.LOCAL_VARIABLE | 給局部變量進(jìn)行注解 |
ElementType.METHOD | 給方法進(jìn)行注解 |
ElementType.PACKAGE | 給包進(jìn)行注解 |
ElementType.PARAMETER | 給一個(gè)方法內(nèi)的參數(shù)進(jìn)行注解 |
ElementType.TYPE | 給一個(gè)類型進(jìn)行注解,比如類、接口、枚舉 |
@Inherited
@Inherited 修飾一個(gè)類時(shí),表明它的注解可以被其子類 繼承 ,缺省情況默認(rèn)是不繼承的。
換句話說:如果一個(gè)子類想獲取到父類上的注解信息,那么必須在父類上使用的注解上面 加上@Inherit關(guān)鍵字
注意:
- @Inherited僅針對(duì)@Target(ElementType.TYPE)類型的annotation有效
- @Inherited 不是表明 注解可以繼承,而是子類可以繼承父類的注解
我們來看一個(gè)示例:
定義一個(gè)注解:
@Inherited
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
使用這個(gè)注解:
@MyReport(value=1)
public class Teacher {
}
則它的子類默認(rèn)繼承了該注解:
public class Student extends Teacher{
}
idea 查看類的繼承關(guān)系:
【圖重截】
@Repeatable
使用@Repeatable這個(gè)元注解來申明注解,表示這個(gè)聲明的注解是可重復(fù)的
@Repeatable 是 Java 1.8 才加進(jìn)來的,所以算是一個(gè)新的特性。
比如:一個(gè)人他既會(huì)下棋又會(huì)做飯,他還會(huì)唱歌。
@Repeatable(MyReport.class)
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
@MyReport(value=0)
@MyReport(value=1)
@MyReport(value=2)
public class Man{
}
自定義注解
我們可以根據(jù)自己的需求定義注解,一般分為以下幾步:
- 新建注解文件, @interface定義注解
public @interface MyReport { }
- 添加參數(shù)、默認(rèn)值
public @interface MyReport {
String name() default "";
int value() default 0;
}
- 用元注解配置注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
我們一般設(shè)置 @Target和@Retention就夠了,其中@Retention一般設(shè)置為RUNTIME,因?yàn)槲覀冏远x的注解通常需要在程序運(yùn)行中讀取。
自定義注解的讀取
讀到這里,相信大家已經(jīng)明白了 如何定義
和使用注解
,我們接下來 就需要如何將注解利用起來。
我們知道讀取注解, 需要用到j(luò)ava的反射
推薦閱讀筆者之前寫過關(guān)于反射的文章:https://mp.weixin.qq.com/s/_n8HTIjkw7Emcunpb4-Iwg
我們先來寫一個(gè)簡單的示例-- 反射獲取注解 :
通過前文的了解,先來改造一下MyAnnotation.java
@Retention(RetentionPolicy.RUNTIME)//確保程序運(yùn)行中,能夠讀取到該注解?。?!
public @interface MyAnnotation {
String msg() default "no msg";
}
我們?cè)儆?code>@MyAnnotation來修飾Person類的類名、屬性、和方法
@MyAnnotation(msg = "this person class")//注解 修飾類
public class Person {
private String name;//姓名
private String sex;//性別
@MyAnnotation(msg = "this person field public")//注解 修飾 public屬性
public int height;//身高
@MyAnnotation(msg = "this person field private")//注解 修飾 private屬性
private int weight;//體重
public void sleep(){
System.out.println(this.name+"--"+ "睡覺");
}
public void eat(){
System.out.println("吃飯");
}
@MyAnnotation(msg = "this person method")//注解 修飾方法
public void dance(){
System.out.println("跳舞");
}
}
-
JAVA
+關(guān)注
關(guān)注
19文章
2973瀏覽量
104939 -
XML
+關(guān)注
關(guān)注
0文章
188瀏覽量
33110 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14364
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論