一. 理解Java注解
注解本質是一個繼承了Annotation的特殊接口,其具體實現類是Java運行時生成的動態代理類。而我們通過反射獲取注解時,返回的是Java運行時生成的動態代理對象$Proxy1。通過代理對象調用自定義注解(接口)的方法,會最終調用AnnotationInvocationHandler的invoke方法。該方法會從memberValues這個Map中索引出對應的值。而memberValues的來源是Java常量池。
實際上Java注解與普通修飾符(public、static、void等)的使用方式並沒有多大區別,下面的例子是常見的注解
public class AnnotationDemo {
@Test
public static void A(){
System.out.println("Test.....");
}
@Deprecated
@SuppressWarnings("uncheck")
public static void B(){
}
}
通過在方法上使用@Test注解后,在運行該方法時,測試框架會自動識別該方法並單獨調用,@Test實際上是一種標記注解,起標記作用,運行時告訴測試框架該方法為測試方法。而對於@Deprecated和@SuppressWarnings(“uncheck”),則是Java本身內置的注解,在代碼中,可以經常看見它們,但這並不是一件好事,畢竟當方法或是類上面有@Deprecated注解時,說明該方法或是類都已經過期不建議再用,@SuppressWarnings 則表示忽略指定警告,比如@SuppressWarnings(“uncheck”),這就是注解的最簡單的使用方式,那么下面我們就來看看注解定義的基本語法
二. 基本語法
聲明注解與元注解
我們先來看看前面的Test注解是如何聲明的:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface OpenAPIMeta {
/**
* 字符參數長度(僅需要對字符串類型進行設置)。
*/
String limit();
/**
* 參數示例值(很重要不要隨意賦值,用於生成示例json)。
*/
String demo();
/**
* 參數說明。
*/
String remark();
/**
* 參數是否必填項(0為非必填 ;1為必填 )
*/
int isRequired() default 0;
/**
* 是否有擴展參數說明
*/
boolean hasExtend() default false;
/**
* 枚舉對象完整類型限定名
*/
String enumType() default "";
}
三. 注解支持的數據類型
所有基本類型(int,float,boolean,byte,double,char,long,short)
String
Class (如:Class<?> 或 Class<T>)
enum
Annotation
上述類型的數組
四. 獲取類級注解
DomainEventHandlerMessageQueue dehmqAnnotation = null;
Annotation[] annotations = obj.getClass().getAnnotations();
for (Annotation x : annotations) {
if (x.annotationType() == DomainEventHandlerMessageQueue.class) {
dehmqAnnotation = x;
break;
}
五. 獲取方法注解
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
OpenAPIMeta apiAnnotation = null;
for (Annotation x : field.getDeclaredAnnotations()) {
if (x.annotationType() == OpenAPIMeta.class) {
apiAnnotation = (OpenAPIMeta) x;
break;
}
}
}
