国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

看到最后,你才發(fā)現(xiàn)Java中注解原來是這么做到的!

開發(fā) 前端
用于定義注解的注解,通常用于注解的定義上,標(biāo)明該注解的使用范圍、生效范圍等。簡而言之,元注解是用來修飾注解的。

?概述

注解想必大家在項目中經(jīng)常使用,比如Spring框架中常用的一些注解:@Controller、@Service、@RequestMapping等等,它是JDK1.5及以后版本引入的一個特性。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對這些元素進(jìn)行說明,注釋。那么你知道JDK什么是元注解嗎?注解有哪些分類嗎?以及注解在Java中最本質(zhì)究竟是什么東西,是如何實現(xiàn)的呢?

注解的分類

根據(jù)注解的使用場景,主要分為三類,元注解、內(nèi)置注解和自定義注解。

元注解

用于定義注解的注解,通常用于注解的定義上,標(biāo)明該注解的使用范圍、生效范圍等。簡而言之,元注解是用來修飾注解的。

@Retention

指定注解信息保留到哪個階段,分別為源代碼階段、編譯Class階段、運(yùn)行階段。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
  • SOURCE: 保留在源代碼java中,被編譯器丟棄,也就是說在class文件中不包含注解信息,通常用來標(biāo)記源碼,引起大家的注意,比如自定義一個注解例如@ThreadSafe,用來標(biāo)識一個類時線程安全的。
  • CLASS: 編譯后的class文件中包含注解信息,但是會被jvm丟棄
  • RUNTIME: 注解信息在運(yùn)行期(JVM)保留(.class也有),可以通過反射機(jī)制讀取注解的信息

@Target

指定注解的使用范圍,如類、方法、屬性、局部屬性、參數(shù)等, 可以多選。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}

具體可選的枚舉如下:

public enum ElementType {
/** 適用范圍:類、接口、注解類型,枚舉類型enum */
TYPE,
/** 作用于類屬性 (includes enum constants) */
FIELD,
/** 作用于方法 */
METHOD,
/** 作用于參數(shù)聲明 */
PARAMETER,
/** 作用于構(gòu)造函數(shù)聲明 */
CONSTRUCTOR,
/** 作用于局部變量聲明 */
LOCAL_VARIABLE,
/** 作用于注解聲明 */
ANNOTATION_TYPE,
/** 作用于包聲明 */
PACKAGE,
/** 作用于類型參數(shù)(泛型參數(shù))聲明 */
TYPE_PARAMETER,
/** 作用于使用類型的任意語句(不包括class) */
TYPE_USE
}

@Inherited

加上該注解的注解,表示可以被標(biāo)注的類子類繼承,比如A上標(biāo)記了帶有@Inherited的注解,那么類B繼承了A, 那么B也會有這個注解,默認(rèn)情況下注解是不支持繼承的。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Document

將此注解包含在 javadoc 中 ,它代表著此注解會被javadoc工具提取成文檔。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Repeatable

1.8中加入的元注解,用來標(biāo)記是否可以重復(fù)標(biāo)記。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
/**
* Indicates the <em>containing annotation type</em> for the
* repeatable annotation type.
* @return the containing annotation type
*/
Class<? extends Annotation> value();
}

內(nèi)置注解

java提供了一些內(nèi)置注解,可以配合編譯器來檢查代碼的正確性, 我們可以關(guān)注他們的元注解。

@Override

標(biāo)記當(dāng)前方法是覆寫父類的方法。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecated

標(biāo)記一個元素為已過期,不要在使用了

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

@SuppressWarnings

用來關(guān)閉編譯器輸出的警告信息

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

@FunctionalInterface

java8中引入,標(biāo)記是一個函數(shù)式接口,也就是說有且只有一個抽象方法的接口

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

自定義注解

注解遵循的格式一般如下:

//元注解部分 xxxx
@Retention(xxxx)
@Target(xxxx)
public @interface 注解名 {
返回值 屬性名() 默認(rèn)值;
返回值 屬性名() 默認(rèn)值;
}
  • 返回值支持的類型如下:java的8種基礎(chǔ)類型(不支持包裝類型)、String、Class、Enum、Annotation、以及上面類型的數(shù)組。
  • 默認(rèn)值可選,非必有。

舉個項目中自定義的栗子:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataAuthorize {
/**
* 資產(chǎn)ID
* @return
*/
String assetId();

/**
* 資產(chǎn)類型
* @return
*/
String assetType();

/**
* 權(quán)限代碼
* @return
*/
String authCode() default "";

/**
* 使用的類型
* @return
*/
Class[] useType();
}

使用反射操作注解

大部分情況下,我們的項目或者開源框架中都定義了大量的注解,而且都是@Retention(RetentionPolicy.RUNTIME)運(yùn)行時階段,我們可以通過反射獲取注解中的信息,所以整體遵循下面的一個范式。

  1. 自定義注解
  2. 掃描注解
  3. 通過反射獲取注解的信息,執(zhí)行相應(yīng)的邏輯。

下面我們重點使用下如何用反射來獲取注解的信息。

  1. 定義target是注解的注解
@Inherited
@Retention( value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.ANNOTATION_TYPE})
public @interface AnnoTest {

String value() default "anno";

}
  1. 定義一個幾乎全量信息的注解
@AnnoTest("alvinAnno")
@Inherited
@Retention( value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE_USE,ElementType.PACKAGE,ElementType.FIELD,
ElementType.TYPE_PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
@Documented
public @interface FullAnnoTest {

String value() default "FullAnnoTest";

}
  1. 定義測試類和反射代碼
@FullAnnoTest("package")
package com.alvin.java.core.anno;

public class ParentObj {
}



@FullAnnoTest("testAnnoReflect")
public class TestAnnoReflect<@FullAnnoTest("parameter") T > extends @FullAnnoTest("parent")ParentObj {

@FullAnnoTest("constructor")
TestAnnoReflect() {
}

//注解字段域
private @FullAnnoTest("name") String name;
//注解泛型字段域
private @FullAnnoTest("value") T value;
//注解通配符
private @FullAnnoTest("list") List<@FullAnnoTest("generic") ?> list;
//注解方法
@FullAnnoTest("method") //注解方法參數(shù)
public String hello(@FullAnnoTest("methodParameter") String name)
throws @FullAnnoTest("Exception") Exception { // 注解拋出異常
//注解局部變量,現(xiàn)在運(yùn)行時暫時無法獲取(忽略)
@FullAnnoTest("result") String result;
result = "siting";
System.out.println(name);
return result;
}

public static void main(String[] args) throws Exception {

TestAnnoReflect<String> TestAnnoReflect = new TestAnnoReflect<> ();
Class<TestAnnoReflect<Object>> clazz = (Class<TestAnnoReflect<Object>>) TestAnnoReflect.getClass();
//class的注解
Annotation[] annotations = clazz.getAnnotations();
FullAnnoTest testTmp = (FullAnnoTest) annotations[0];
System.out.println("修飾TestAnnoReflect.class注解value: "+testTmp.value());
//構(gòu)造器的注解
Constructor<TestAnnoReflect<Object>> constructor = (Constructor<TestAnnoReflect<Object>>) clazz.getDeclaredConstructors()[0];
testTmp = constructor.getAnnotation(FullAnnoTest.class);
System.out.println("修飾構(gòu)造器的注解value: "+testTmp.value());
//繼承父類的注解
AnnotatedType annotatedType = clazz.getAnnotatedSuperclass();
testTmp = annotatedType.getAnnotation(FullAnnoTest.class);
System.out.println("修飾繼承父類的注解value: "+testTmp.value());
//注解的注解
AnnoTest AnnoTest = testTmp.annotationType().getAnnotation(AnnoTest.class);
System.out.println("修飾注解的注解AnnoTest-value: "+AnnoTest.value());
//泛型參數(shù) T 的注解
TypeVariable<Class<TestAnnoReflect<Object>>> variable = clazz.getTypeParameters()[0];
testTmp = variable.getAnnotation(FullAnnoTest.class);
System.out.println("修飾泛型參數(shù)T注解value: "+testTmp.value());
//普通字段域 的注解
Field[] fields = clazz.getDeclaredFields();
Field nameField = fields[0];
testTmp = nameField.getAnnotation(FullAnnoTest.class);
System.out.println("修飾普通字段域name注解value: "+testTmp.value());
//泛型字段域 的注解
Field valueField = fields[1];
testTmp = valueField.getAnnotation(FullAnnoTest.class);
System.out.println("修飾泛型字段T注解value: "+testTmp.value());
//通配符字段域 的注解
Field listField = fields[2];
AnnotatedParameterizedType annotatedPType = (AnnotatedParameterizedType)listField.getAnnotatedType();
testTmp = annotatedPType.getAnnotation(FullAnnoTest.class);
System.out.println("修飾泛型注解value: "+testTmp.value());
//通配符注解 的注解
AnnotatedType[] annotatedTypes = annotatedPType.getAnnotatedActualTypeArguments();
AnnotatedWildcardType annotatedWildcardType = (AnnotatedWildcardType) annotatedTypes[0];
testTmp = annotatedWildcardType.getAnnotation(FullAnnoTest.class);
System.out.println("修飾通配符注解value: "+testTmp.value());
//方法的注解
Method method = clazz.getDeclaredMethod("hello", String.class);
annotatedType = method.getAnnotatedReturnType();
testTmp = annotatedType.getAnnotation(FullAnnoTest.class);
System.out.println("修飾方法的注解value: "+testTmp.value());
//異常的注解
annotatedTypes = method.getAnnotatedExceptionTypes();
testTmp = annotatedTypes[0].getAnnotation(FullAnnoTest.class);
System.out.println("修飾方法拋出錯誤的注解value: "+testTmp.value());
//方法參數(shù)的注解
annotatedTypes = method.getAnnotatedParameterTypes();
testTmp = annotatedTypes[0].getAnnotation(FullAnnoTest.class);
System.out.println("修飾方法參數(shù)注解value: "+testTmp.value());
//包的注解
Package p = Package.getPackage("com.alvin.java.core.anno");
testTmp = p.getAnnotation(FullAnnoTest.class);
System.out.println("修飾package注解value: "+testTmp.value());
TestAnnoReflect.hello("hello");
}

}
  1. 查看對應(yīng)的執(zhí)行結(jié)果
修飾TestAnnoReflect.class注解value: testAnnoReflect
修飾構(gòu)造器的注解value: constructor
修飾繼承父類的注解value: parent
修飾注解的注解AnnoTest-value: alvinAnno
修飾泛型參數(shù)T注解value: parameter
修飾普通字段域name注解value: name
修飾泛型字段T注解value: value
修飾泛型注解value: list
修飾通配符注解value: generic
修飾方法的注解value: method
修飾方法拋出錯誤的注解value: Exception
修飾方法參數(shù)注解value: methodParameter
修飾package注解value: package
hello

注解的本質(zhì)和底層實現(xiàn)

大家有沒有想過注解的本質(zhì)是什么?

我們先通過反編譯查看注解生成的字節(jié)碼,可以通過javap -v FullAnnoTest.class查看如下:

圖片

可以看到,我們的注解是繼承自Annotation接口。

public interface Annotation {
boolean equals(Object obj);

int hashCode();

String toString();

/**
* Returns the annotation type of this annotation.
* @return the annotation type of this annotation
*/
Class<? extends Annotation> annotationType();
}

所以注解相當(dāng)于一個語法糖一樣,可以方便我們使用,本質(zhì)上它是繼承自Annotation的一個接口。

那大家有沒有想過它的實現(xiàn)類在哪里?比如下面的代碼,獲取到注解,按照上面的解釋,它是一個接口,那調(diào)用value()方法時,它具體調(diào)用的哪個實現(xiàn)類呢?我們并沒有寫實現(xiàn)類啊.....

答案當(dāng)然就是動態(tài)代理生成的實現(xiàn)類。

AnnoTest annoTest = testTmp.annotationType().getAnnotation(AnnoTest.class);
System.out.println("修飾注解的注解AnnoTest-value: "+annoTest.value());

我們可以在啟動參數(shù)添加如下命令可以查看生成的代理類:-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true

圖片

執(zhí)行后,生成代理類如下,

圖片

代理大致的代碼如下:

public final class $Proxy2 extends Proxy implements FullAnnoTest {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m0;
private static Method m3;

public $Proxy2(InvocationHandler var1) throws {
super(var1);
}

public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}



public final Class annotationType() throws {
try {
return (Class)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final String value() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.alvin.java.core.anno.FullAnnoTest").getMethod("annotationType");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("com.alvin.java.core.anno.FullAnnoTest").getMethod("value");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

我們看value()?方法,這里調(diào)用了super.h對象,也就是InvocationHandler?對象,而我們注解用的是AnnotationInvocationHandler這個子類,我們在invoke方法中打個斷點,就明白了~~

責(zé)任編輯:武曉燕 來源: JAVA旭陽
相關(guān)推薦

2022-01-14 14:19:38

ReactTS前端

2020-02-23 15:55:00

疫情AI人工智能

2021-02-07 08:13:18

@DateTimeFo@NumberFormSpring

2017-11-12 21:12:34

HPC

2019-10-08 12:32:07

運(yùn)維架構(gòu)技術(shù)

2025-04-03 10:39:56

2021-07-29 16:56:59

微信騰訊注冊

2020-06-30 08:12:32

VMwareKVMDocker

2022-08-15 08:01:00

三色標(biāo)記JVM算法

2025-07-03 07:05:00

JavaScriptPromise代碼

2024-10-11 11:59:03

2017-06-06 15:13:07

2021-08-17 07:00:00

雙重檢查鎖Nacos

2020-05-26 08:52:36

Java JVM多態(tài)

2022-12-14 07:32:40

InnoDBMySQL引擎

2023-07-26 00:32:33

注解抽象spring

2015-08-05 10:50:01

Facebook緩存網(wǎng)頁

2013-03-29 09:54:05

創(chuàng)業(yè)創(chuàng)業(yè)者

2020-09-24 06:44:54

HTTPS網(wǎng)站 HTTP

2022-05-05 08:55:12

工業(yè)物聯(lián)網(wǎng)IIoT
點贊
收藏

51CTO技術(shù)棧公眾號

国产911在线观看| 四虎国产精品永远| 五月婷婷六月综合| 久久久这里只有精品视频| 在线精品国产亚洲| 一区二区三区四区视频免费观看| 欧美日韩一区中文字幕| 成人精品3d动漫| 日本一区二区三区dvd视频在线| 伊人婷婷久久| 久久av一区| 国产精品一码二码三码在线| 国产精品欧美日韩一区| 欧美高清第一页| 国产aⅴ精品一区二区四区| 国产视频综合在线| 僵尸再翻生在线观看| 欧美va在线播放| 国产在线高潮| 日韩一区二区三区视频| 国产在线网站| 欧美日韩免费观看一区三区| 四虎影视精品成人| 黄网站色欧美视频| 青青草在线视频免费观看| 疯狂欧美牲乱大交777| 天堂а√在线8种子蜜桃视频| 亚洲妇熟xx妇色黄| 视频在线91| 欧美日韩中文在线观看| 中文字幕欧美一区二区| 亚洲一区免费观看| 在线观看h网址| 欧美在线综合视频| 色帝国亚洲欧美在线| 亚洲国产成人在线播放| 韩国成人免费视频| 亚洲天堂av电影| 精品3atv在线视频| 欧美精品在线观看| 猫咪成人在线观看| 国产精品入口福利| 欧美人成在线| 亚洲资源在线网| www.日韩精品| 九色porn| 7777精品久久久大香线蕉| 19禁羞羞电影院在线观看| 夜夜嗨av一区二区三区免费区| 99久久这里有精品| 国产v综合ⅴ日韩v欧美大片| 一区二区三区网站| 水蜜桃一区二区| 成人精品一区二区三区四区| 色偷偷亚洲女人天堂观看欧| 都市激情亚洲色图| av2020不卡| 超碰精品一区二区三区乱码| 久久av影视| 久久久久久久久久久一区| 久久电影网站中文字幕| 15—17女人毛片| 欧美午夜女人视频在线| 波多野结衣在线高清| 久操成人在线视频| 亚洲91久久| 穿情趣内衣被c到高潮视频| 国产精品久久久久影院老司| 在线观看美女网站大全免费| 色av中文字幕一区| 一本一本久久a久久综合精品| 欧美性受xxxx黑人猛交88| 国产精品久久久久久福利一牛影视| 深夜福利视频在线免费观看| 亚洲成av人片在线观看香蕉| 精品福利网址导航| 欧美一级二级三级九九九| 国产色婷婷亚洲99精品小说| 欧美成人精品一区二区男人看| 久久艳片www.17c.com| 在线播放日韩| 三级视频中文字幕| 日韩精品一区在线| 久久91成人| 久久久久久久久影视| 激情亚洲一区二区三区四区| 99蜜月精品久久91| 国产精品久久精品视| 中文字幕欧美区| 免费网站免费进入在线| 欧美精品激情blacked18| 亚洲在线网站| 伊人影院综合在线| 亚洲白虎美女被爆操| 日韩在线看片| 免费在线观看亚洲视频| 欧美性猛交xxxxxxxx| 一本色道69色精品综合久久| 日韩av在线电影观看| 一区二区三区在线免费播放| 亚洲成人短视频| 精品国产乱码久久久久软件| 国产精品网站一区| 亚洲风情在线资源| 91在线看网站| 中文在线资源观看网站视频免费不卡 | 久久伊人免费视频| 亚洲欧美不卡| 污视频在线观看免费| 久久久久久久久久国产| 国产成人精品影视| 蜜桃成人365av| 91久色国产| 夜夜精品视频一区二区| 精品网站在线| 青青草原亚洲| 欧美福利电影网| 天天超碰亚洲| 一级毛片高清视频| 91黄色8090| 久久精品在线免费观看| 91久久国产综合久久91猫猫| 蜜桃麻豆91| 欧美喷潮久久久xxxxx| 天天av综合| 色佬视频在线观看| 日本sm极度另类视频| 国产日韩欧美高清在线| 伊人久久大香伊蕉在人线观看热v| 三级在线免费观看| 亚洲成人网av| 日本免费新一区视频| 国产激情小视频在线| 国产欧美欧洲| 欧美日韩第一区日日骚| 亚洲第一毛片| 中文字幕日韩欧美在线 | 国产亚av手机在线观看| 国内一区二区三区在线视频| 色综合久久综合网97色综合 | 神马久久精品| 成人三级在线| 欧美高清视频一二三区| 久久久水蜜桃av免费网站| 成人福利片网站| 日韩精品一区二区三区外面 | 九九热这里只有精品免费看| 久久亚洲一级片| 日本一区二区三区电影免费观看| 91免费视频网站在线观看| 欧美大码xxxx| 亚洲免费观看视频| 色婷婷一区二区三区| 欧美在线一卡| 久久综合九色欧美狠狠| 日韩精品免费看| 免费福利片在线观看| 日韩精品免费一区二区三区竹菊 | 成人免费a**址| 又黄又www的网站| 成人国产精品久久久久久亚洲| 欧美午夜视频在线观看| 欧美精品日韩| 俄罗斯一级**毛片在线播放| 欧美日韩午夜爽爽| 欧美丰满老妇厨房牲生活| 亚洲图片欧美一区| 国产精品日本| 99re久久| 国产主播在线资源| y111111国产精品久久婷婷| 日韩一区二区精品| 99精品久久久久久| 欧美精选视频在线观看| 亚洲成人三级| 久久手机在线视频| 日韩免费观看在线观看| 9191久久久久久久久久久| 午夜精彩视频| 国产综合第一页| 亚洲色图校园春色| 亚洲精品久久7777| 午夜影院日韩| 四虎影视国产精品| 日韩专区一区二区| 黄色成人在线免费观看| 91精品国产精品| 91精品国产综合久久久久| 波多野结衣在线aⅴ中文字幕不卡| 六月丁香久久丫| 色a资源在线| 免费男女羞羞的视频网站中文字幕| 免费99视频| 国产91对白在线播放| 日韩一级免费观看| 国产精品色噜噜| 国产在线精品视频| 欧美激情欧美| 四虎精品在线观看| 国产福利电影在线|