自己開發註解

自己開發註解

什麼是java註解?

註解是加在java代碼中的一些特殊標記,可以在編譯期間/類加載期間/運行期間/獲取到註解信息,然後執行相應的處理

註解可以加在方法前、類和接口前、方法參數前等,可以使用`@Target`元註解來指定

使用註解的好處,爲什麼要使用註解?

使用註解可以取代xml配置文件。

註解並不影響源代碼的運行

註解的壞處

java註解會需要使用java反射的機制,會大大降低性能。java反射會影響系統性能

註解的維護性有問題需要改源代碼,解耦性稍差

示例:開發一個類似JUnit的@Test註解

  • 開發註解,要使用@Retention元註解設定好註解的生存時間。在reflect包下創建一個Annotation,名爲Test

    package reflect;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    /**
     * 如果一個註解沒有任何的屬性,一般稱之爲標識註解
     * 註解默認情況下只會保留到字節碼文件裏面,運行時就會被刪除.
     * 如果希望在運行時仍然能夠訪問到註解,需要設置註解的生成時間
     * @Retention 是一個元註解(即由系統提供,專門用來解釋其他的註解的註解)
     */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test {
    	
    }
    
  • 將註解添加入源代碼

    reflect包下創建一個類,名爲C

    package reflect;
    
    public class C {
    	public void f1() {
    		System.out.println("C.f1()");
    	}
    	
    	@Test
    	public void f2() {
    		System.out.println("C.f2()");
    	}
    	
    	public void hello() {
    		System.out.println("C.hello()");
    	}
    }
    
  • 利用反射機制將註解讀取出來,按照業務的需要進行相應的處理

    reflect包下創建一個測試類,名爲AnnotationTest

    package reflect;
    
    import java.lang.reflect.Method;
    import java.util.Scanner;
    
    public class AnnotationTest {
    	public static void main(String[] args) throws Exception {
    		Scanner scanner = new Scanner(System.in);
    		String className = scanner.nextLine();
    		// 利用反射,獲取類對象
    		Class cls = Class.forName(className);
    		// 實例化(此種方式實例化要求必須有無參構造器)
    		Object obj = cls.newInstance();
    		// 獲得該類的所有方法。
    		// Method用來描述一個方法(包括方法名、參數類型、返回類型,加在方法前的註解等等)
    		Method[] methods = cls.getDeclaredMethods();
    		for(Method mh : methods) {
    			// 獲得加載方法前的@Test註解(參數是註解對應的class對象)
    			Test test = mh.getAnnotation(Test.class);
    			System.out.println("@Test="+test);
    			if(test != null) {
    				// 只執行帶有@Test註解的方法
    				mh.invoke(obj);
    			}
    		}
    	}
    }
    
    

    執行此main方法,在控制檯中輸入reflect.C,打印結果如下(可以看到該註解方法被執行了):

    reflect.C
    
    @Test=null
    @[email protected]()
    C.f2()
    @Test=null
    

  • 給註解添加屬性

    註解Test

    package reflect;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    /**
     * 如果一個註解沒有任何的屬性,一般稱之爲標識註解
     * 註解默認情況下只會保留到字節碼文件裏面,運行時就會被刪除.
     * 如果希望在運行時仍然能夠訪問到註解,需要設置註解的生成時間
     * @Retention 是一個元註解(即由系統提供,專門用來解釋其他的註解的註解)
     */
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test {
    	/*
    	 * value是註解的屬性(不是方法),類型是String
    	 * 類型可以是基本類型,註解類型,數組等等
    	 * 如果註解名爲value,且只有一個屬性,則該註解在使用時,不需要寫屬性名
    	 */
    	public String value();
    }
    
    

    源代碼類C(使用註解的類)

    package reflect;
    
    public class C {
    	public void f1() {
    		System.out.println("C.f1()");
    	}
    	
    	@Test(value="hello")
    	public void f2() {
    		System.out.println("C.f2()");
    	}
    	
    	public void hello() {
    		System.out.println("C.hello()");
    	}
    	
    	
    }
    
    

    測試類

    package reflect;
    
    import java.lang.reflect.Method;
    import java.util.Scanner;
    
    public class AnnotationTest {
    	public static void main(String[] args) throws Exception {
    		Scanner scanner = new Scanner(System.in);
    		String className = scanner.nextLine();
    		// 利用反射,獲取類對象
    		Class cls = Class.forName(className);
    		// 實例化(此種方式實例化要求必須有無參構造器)
    		Object obj = cls.newInstance();
    		// 獲得該類的所有方法。
    		// Method用來描述一個方法(包括方法名、參數類型、返回類型,加在方法前的註解等等)
    		Method[] methods = cls.getDeclaredMethods();
    		for(Method mh : methods) {
    			// 獲得加載方法前的@Test註解(參數是註解對應的class對象)
    			Test test = mh.getAnnotation(Test.class);
    			System.out.println("@Test="+test);
    			if(test != null) {
    				// 只執行帶有@Test註解的方法
    				mh.invoke(obj);
    				// 讀取註解的屬性值
    				String v = test.value();
    				System.out.println("註解屬性值v:"+v);
    			}
    		}
    	}
    }
    
    

    執行此main方法,在控制檯中輸入reflect.C,打印結果如下(可以看到該註解方法被執行了,也打印出了屬性值):

    reflect.C
    
    @Test=null
    @[email protected](value=hello)
    C.f2()
    註解屬性值v:hello
    @Test=null
    



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章