一. 理解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; } } }