註解的定義
註解經過@interface定義java
public @interface Log { }
它的關鍵字和接口定義方式差很少,只不過前面多了一個@符號函數
註解的應用
註解的應用方式很簡單在類或者方法的上方加一@xx就行了,具體的後面講工具
public class Controller { @Log public void test(){ } } @Log public class Controller { public void test(){ } }
元註解
元註解:就是定義註解的註解,是一種基本的註解能夠定義到註解上的註解測試
@Retention
用來講明註解的生命週期.net
-
@Retention(RetentionPolicy.SOURCE) 註解只在源碼階段保留,編譯期就被丟棄了code
-
@Retention(RetentionPolicy.CLASS) 默認策略,註解只被保留到編譯進行的時候,它並不會被加載到 JVM 中。blog
-
@Retention(RetentionPolicy.RUNTIME) 註解能夠保留到程序運行的時候,它會被加載進入到 JVM 中,因此程序運行時也能夠獲取到它。接口
@Documented
Documented註解代表這個註釋是由 javadoc記錄的,在默認狀況下也有相似的記錄工具。 若是一個類型聲明被註釋了文檔化,它的註釋成爲公共API的一部分。生命週期
@Target說明註解的做用目標
-
@Target(ElementType.TYPE) 接口、類、枚舉、註解文檔
-
@Target(ElementType.FIELD) 字段、枚舉的常量
-
@Target(ElementType.METHOD) 方法
-
@Target(ElementType.PARAMETER) 方法參數
-
@Target(ElementType.CONSTRUCTOR) 構造函數
-
@Target(ElementType.LOCAL_VARIABLE) 局部變量
-
@Target(ElementType.ANNOTATION_TYPE) 註解
-
@Target(ElementType.PACKAGE) 包
@Inherited
@Inherited:若是一個使用了此註解的註解1,被一個class使用,那麼這個註解1也對class的子類生效。例如:
@Inherited @Target(ElementType.METHOD) public @interface Log { } @Log public class testA(){} public class testB() extends testA{}
testA應用了@Log這個註解,那麼testB這個類上面也有@Log這個註解。
@Repeatable
例如:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Logs { Log[] value(); } @Repeatable(Logs.class) public @interface Log{ String descr() default ""; } public class Controller { @Log(descr="描述1") @Log(descr="描述2") public void test(){ } } public class LogRunner { public static void main(String []args) throws Exception{ System.out.println("開始時間:"+new Date()); Class classs=Controller.class; Method[] ms=classs.getMethods(); for(Method method:ms){ boolean flag=method.isAnnotationPresent(Logs.class); if(flag){ Logs logs=method.getAnnotation(Logs.class); for(Log log:logs.value()){ System.out.println(log.descr()); } } } } }
輸出的時候就會輸出,描述1,描述2.
實現自定義註解
第一步先定義一個註解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface Log { String methodName() default "defaultAMethod"; String controller() default "defaultController"; String descr() default "defaultDescr"; }
第二步應用這個註解
public class Controller { @Log public void test(){ System.out.println("結束時間:"+new Date()); } }
第三步經過反射讓這個註解起做用
public class LogRunner { public static void main(String []args) throws Exception{ System.out.println("開始時間:"+new Date()); Class classs=Controller.class; Method[] ms=classs.getMethods(); for(Method method:ms){ boolean flag=method.isAnnotationPresent(Log.class); if(flag){ Log log=method.getAnnotation(Log.class); System.out.println(log.methodName()); System.out.println(log.descr()); System.out.println(log.controller()); method.invoke(classs.newInstance(),null); } } } }
輸出結果
若是將第二步方法上面的註解不使用默認的value,將代碼改爲
public class Controller { @Log(methodName = "test",controller = "testController",descr = "測試") public void test(){ System.out.println("結束時間:"+new Date()); } }
那麼將會輸出