深入 Java自定義註解

        Java深入 - 深入 Java自定義註解

分類: Java深入系列 1222人閱讀 評論(0) 收藏 舉報

我們在使用Spring框架的時候,會經常使用類似:@Autowired 這樣的註解。我們也可以自己定義一些註解。Java的註解主要在包:java.lang.annotation中實現。

1. 元註解

什麼是元註解?你可以這樣理解,元註解是自定義註解的註解。元註解主要包含4個。他們主要在java.lang.annotation中可以找到。我們自己要創建註解的時候必須要用到這些元註解。所以必須徹底理解這四個元註解的含義。

1. @Documented

2. @Inherited

3. @Retention

4. @Target

例如:

  1. package com.test.www;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Inherited;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10.   
  11.   
  12. /** 
  13.  * 定義一個用戶名的自定義註解 
  14.  * @author zhuli 
  15.  * @date 2014-7-5 
  16.  */  
  17. @Documented  
  18. @Retention(RetentionPolicy.RUNTIME)  
  19. @Target({ ElementType.TYPE, ElementType.METHOD})  
  20. @Inherited  
  21. public @interface UserNameAnnotations {  
  22.   
  23.     public String value() default "";  
  24.   
  25. }  
package com.test.www;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;



/**
 * 定義一個用戶名的自定義註解
 * @author zhuli
 * @date 2014-7-5
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD})
@Inherited
public @interface UserNameAnnotations {

    public String value() default "";

}

1. @Documented

@Documented用於描述其它類型的annotation應該被作爲被標註的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。

2. @Inherited

@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。

3. @Target

@Target說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。

ElementType.CONSTRUCTOR  作用於構造器
ElementType.FIELD  作用於域/屬性
ElementType.LOCAL_VARIABLE  用於描述局部變量
ElementType.METHOD  作用於方法
ElementType.PACKAGE   用於描述包
ElementType.PARAMETER   用於描述參數
ElementType.TYPE   用於描述類、接口(包括註解類型) 或enum聲明,最常用

單個修飾對象的範圍:

  1. @Target(ElementType.TYPE)  
@Target(ElementType.TYPE)

多個:

  1. @Target({ ElementType.TYPE, ElementType.METHOD})  
@Target({ ElementType.TYPE, ElementType.METHOD})

4. Retention

定義了該Annotation被保留的時間長短:某些Annotation僅出現在源代碼中,而被編譯器丟棄;而另一些卻被編譯在class文件中;編譯在class文件中的Annotation可能會被虛擬機忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因爲Annotation與class在使用上是被分離的)。使用這個meta-Annotation可以對 Annotation的“生命週期”限制。

RetentionPolicy.RUNTIME 註解會在class字節碼文件中存在,在運行時可以通過反射獲取到

RetentionPolicy.CLASS 默認的保留策略,註解會在class字節碼文件中存在,但運行時無法獲得

RetentionPolicy.SOURCE 註解僅存在於源碼中,在class字節碼文件中不包含


2. 創建一個自定義註解 - 作用於類

1. 創建一個註解類

  1. package com.test.www;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Inherited;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10.   
  11.   
  12. /** 
  13.  * 定義一個用戶名的自定義註解 
  14.  * @author zhuli 
  15.  * @date 2014-7-5 
  16.  */  
  17. @Documented //文檔  
  18. @Retention(RetentionPolicy.RUNTIME) //在運行時可以獲取  
  19. @Target({ ElementType.TYPE, ElementType.METHOD}) //作用到類,方法,接口上等  
  20. @Inherited //子類會繼承  
  21. public @interface UserNameAnnotations {  
  22.       
  23.     public String value() default ""//使用的時候 @UserNameAnnotations(value="xxx")  
  24.   
  25. }  
package com.test.www;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;



/**
 * 定義一個用戶名的自定義註解
 * @author zhuli
 * @date 2014-7-5
 */
@Documented //文檔
@Retention(RetentionPolicy.RUNTIME) //在運行時可以獲取
@Target({ ElementType.TYPE, ElementType.METHOD}) //作用到類,方法,接口上等
@Inherited //子類會繼承
public @interface UserNameAnnotations {
    
    public String value() default ""; //使用的時候 @UserNameAnnotations(value="xxx")

}

2. 創建一個Test類

  1. package com.test.www;  
  2.   
  3.   
  4. /** 
  5.  * 一個註解的測試類 
  6.  * @author zhuli 
  7.  * @date 2014-7-5 
  8.  */  
  9. //注入註解作用於類上面  
  10. //可以通過反射 獲取類的信息之後 獲取得到這個註解的值  
  11. @UserNameAnnotations(value = "initphp")   
  12. public class Test {  
  13.   
  14.     private String userName;  
  15.   
  16.     public String getUserName() {  
  17.         return userName;  
  18.     }  
  19.   
  20.     public void setUserName(String userName) {  
  21.         this.userName = userName;  
  22.     }  
  23.   
  24. }  
package com.test.www;


/**
 * 一個註解的測試類
 * @author zhuli
 * @date 2014-7-5
 */
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp") 
public class Test {

    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}


3. 測試類

  1. package com.test.www;  
  2.   
  3.   
  4. public class mainTest {  
  5.   
  6.     public static void main(String[] args) {  
  7.         Class<Test> testClass = Test.class;  
  8.         //因爲註解是作用於類上面的,所以可以通過isAnnotationPresent來判斷是否是一個  
  9.         //有UserNameAnnotations註解的類  
  10.         if (testClass.isAnnotationPresent(UserNameAnnotations.class)) {  
  11.             System.out.println("this is a Annotations class");  
  12.             //通過getAnnotation可以獲取註解對象  
  13.             UserNameAnnotations userNameAnnotations = (UserNameAnnotations) testClass.  
  14. getAnnotation(UserNameAnnotations.class);  
  15.             if (userNameAnnotations != null) {  
  16.                 System.out.println("value:" + userNameAnnotations.value());  
  17.             } else {  
  18.                 System.out.println("null");  
  19.             }  
  20.         } else {  
  21.             System.out.println("this is not Annotations class");  
  22.         }  
  23.   
  24.     }  
  25. }  
package com.test.www;


public class mainTest {

    public static void main(String[] args) {
        Class<Test> testClass = Test.class;
        //因爲註解是作用於類上面的,所以可以通過isAnnotationPresent來判斷是否是一個
        //有UserNameAnnotations註解的類
        if (testClass.isAnnotationPresent(UserNameAnnotations.class)) {
            System.out.println("this is a Annotations class");
            //通過getAnnotation可以獲取註解對象
            UserNameAnnotations userNameAnnotations = (UserNameAnnotations) testClass.
getAnnotation(UserNameAnnotations.class);
            if (userNameAnnotations != null) {
                System.out.println("value:" + userNameAnnotations.value());
            } else {
                System.out.println("null");
            }
        } else {
            System.out.println("this is not Annotations class");
        }

    }
}

4. 輸出:

  1. this is a Annotations class  
  2. value:initphp  
this is a Annotations class
value:initphp


3. 創建一個自定義註解 - 作用於方法

1. 自定義註解類

  1. package com.test.www;  
  2.   
  3.   
  4. import java.lang.annotation.Documented;  
  5. import java.lang.annotation.ElementType;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10. /** 
  11.  * 定義一個作用到方法的註解 
  12.  * @author zhuli.zhul 
  13.  * @date 2014-7-5 
  14.  */  
  15. @Documented//文檔  
  16. @Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取  
  17. @Target({ ElementType.TYPE, ElementType.METHOD })//作用到類,方法,接口上等  
  18. public @interface MethodType {  
  19.   
  20.     //枚舉類型  
  21.     public enum MethodTypeEnum {  
  22.         TYPE1, TYPE2  
  23.     }  
  24.   
  25.     //實際的值  
  26.     public MethodTypeEnum methodType() default MethodTypeEnum.TYPE1;  
  27. }  
package com.test.www;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定義一個作用到方法的註解
 * @author zhuli.zhul
 * @date 2014-7-5
 */
@Documented//文檔
@Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
@Target({ ElementType.TYPE, ElementType.METHOD })//作用到類,方法,接口上等
public @interface MethodType {

    //枚舉類型
    public enum MethodTypeEnum {
        TYPE1, TYPE2
    }

    //實際的值
    public MethodTypeEnum methodType() default MethodTypeEnum.TYPE1;
}

2. 創建一個使用註解的類

  1. package com.test.www;  
  2.   
  3. import com.test.www.MethodType.MethodTypeEnum;  
  4.   
  5.   
  6. /** 
  7.  * 一個註解的測試類 
  8.  * @author zhuli 
  9.  * @date 2014-7-5 
  10.  */  
  11. //注入註解作用於類上面  
  12. //可以通過反射 獲取類的信息之後 獲取得到這個註解的值  
  13. @UserNameAnnotations(value = "initphp")   
  14. public class Test {  
  15.   
  16.     private String userName;  
  17.   
  18.     //註解到  
  19.     @MethodType(methodType=MethodTypeEnum.TYPE2)  
  20.     public String getUserName() {  
  21.         return userName;  
  22.     }  
  23.   
  24.     public void setUserName(String userName) {  
  25.         this.userName = userName;  
  26.     }  
  27.   
  28. }  
package com.test.www;

import com.test.www.MethodType.MethodTypeEnum;


/**
 * 一個註解的測試類
 * @author zhuli
 * @date 2014-7-5
 */
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp") 
public class Test {

    private String userName;

    //註解到
    @MethodType(methodType=MethodTypeEnum.TYPE2)
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

3. 創建main入口

  1. package com.test.www;  
  2.   
  3.   
  4. import java.lang.reflect.Method;  
  5.   
  6. import com.test.www.MethodType.MethodTypeEnum;  
  7.   
  8. public class mainTest {  
  9.   
  10.     public static void main(String[] args) {  
  11.         Class<Test> testClass = Test.class;  
  12.         try {  
  13.             //因爲是註解到method上的,所以首先要獲取這個方法  
  14.             Method method = testClass.getDeclaredMethod("getUserName");  
  15.               
  16.             //判斷這個方法上是否有這個註解  
  17.             if (method.isAnnotationPresent(MethodType.class)) {  
  18.                 System.out.println("this is a method Annotation");  
  19.                   
  20.                 //如果有這個註解,則獲取註解類  
  21.                 MethodType methodType = (MethodType) method.getAnnotation(MethodType.class);  
  22.                 if (methodType != null) {  
  23.                     if (MethodTypeEnum.TYPE1.equals(methodType.methodType())) {  
  24.                         System.out.println("this is TYPE1");  
  25.                     } else {  
  26.                         System.out.println("this is TYPE2");  
  27.                     }  
  28.                 }  
  29.             } else {  
  30.                 System.out.println("this is not  a method Annotation");  
  31.             }  
  32.   
  33.         } catch (Exception e) {  
  34.         }  
  35.   
  36.     }  
  37. }  
package com.test.www;


import java.lang.reflect.Method;

import com.test.www.MethodType.MethodTypeEnum;

public class mainTest {

    public static void main(String[] args) {
        Class<Test> testClass = Test.class;
        try {
            //因爲是註解到method上的,所以首先要獲取這個方法
            Method method = testClass.getDeclaredMethod("getUserName");
            
            //判斷這個方法上是否有這個註解
            if (method.isAnnotationPresent(MethodType.class)) {
                System.out.println("this is a method Annotation");
                
                //如果有這個註解,則獲取註解類
                MethodType methodType = (MethodType) method.getAnnotation(MethodType.class);
                if (methodType != null) {
                    if (MethodTypeEnum.TYPE1.equals(methodType.methodType())) {
                        System.out.println("this is TYPE1");
                    } else {
                        System.out.println("this is TYPE2");
                    }
                }
            } else {
                System.out.println("this is not  a method Annotation");
            }

        } catch (Exception e) {
        }

    }
}

4. 輸出:

  1. this is a method Annotation  
  2. this is TYPE2  
this is a method Annotation
this is TYPE2


4. 創建一個自定義註解 - 作用於域

1. 創建一個自定義註解

  1. package com.test.www;  
  2.   
  3.   
  4. import java.lang.annotation.Documented;  
  5. import java.lang.annotation.ElementType;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10. /** 
  11.  * 定義一個作用到域上的自定義註解 
  12.  * @author zhuli 
  13.  * @date 2014-7-5 
  14.  */  
  15. @Documented//文檔  
  16. @Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取  
  17. @Target({ ElementType.FIELD })//作用到類的域上面  
  18. public @interface FieldAnnotations {  
  19.   
  20.     public String value() default ""//使用的時候 @FieldAnnotations(value="xxx")  
  21.   
  22. }  
package com.test.www;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定義一個作用到域上的自定義註解
 * @author zhuli
 * @date 2014-7-5
 */
@Documented//文檔
@Retention(RetentionPolicy.RUNTIME)//在運行時可以獲取
@Target({ ElementType.FIELD })//作用到類的域上面
public @interface FieldAnnotations {

    public String value() default ""; //使用的時候 @FieldAnnotations(value="xxx")

}

2. 創建一個使用註解的類

  1. package com.test.www;  
  2.   
  3. import com.test.www.MethodType.MethodTypeEnum;  
  4.   
  5.   
  6. /** 
  7.  * 一個註解的測試類 
  8.  * @author zhuli 
  9.  * @date 2014-7-5 
  10.  */  
  11. //注入註解作用於類上面  
  12. //可以通過反射 獲取類的信息之後 獲取得到這個註解的值  
  13. @UserNameAnnotations(value = "initphp")   
  14. public class Test {  
  15.   
  16.     @FieldAnnotations(value="zhuli")  
  17.     private String userName;  
  18.   
  19.     //註解到  
  20.     @MethodType(methodType=MethodTypeEnum.TYPE2)  
  21.     public String getUserName() {  
  22.         return userName;  
  23.     }  
  24.   
  25.     public void setUserName(String userName) {  
  26.         this.userName = userName;  
  27.     }  
  28.   
  29. }  
package com.test.www;

import com.test.www.MethodType.MethodTypeEnum;


/**
 * 一個註解的測試類
 * @author zhuli
 * @date 2014-7-5
 */
//注入註解作用於類上面
//可以通過反射 獲取類的信息之後 獲取得到這個註解的值
@UserNameAnnotations(value = "initphp") 
public class Test {

    @FieldAnnotations(value="zhuli")
    private String userName;

    //註解到
    @MethodType(methodType=MethodTypeEnum.TYPE2)
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

3. 創建main入口類

  1. package com.test.www;  
  2.   
  3.   
  4. import java.lang.reflect.Field;  
  5.   
  6. public class mainTest {  
  7.   
  8.     public static void main(String[] args) {  
  9.         Test test = new Test();  
  10.         Class<Test> testClass = Test.class;  
  11.         try {  
  12.             //因爲是註解到Field上的,所以首先要獲取這個字段  
  13.             Field field = testClass.getDeclaredField("userName");  
  14.   
  15.             //判斷這個Field上是否有這個註解  
  16.             if (field.isAnnotationPresent(FieldAnnotations.class)) {  
  17.                 System.out.println("this is a field Annotation");  
  18.   
  19.                 //如果有這個註解,則獲取註解類  
  20.                 FieldAnnotations fieldAnnotations = (FieldAnnotations) field.getAnnotation(FieldAnnotations.class);  
  21.                 if (fieldAnnotations != null) {  
  22.                     //通過反射給私有變量賦值  
  23.                     field.setAccessible(true);  
  24.                     field.set(test, fieldAnnotations.value());  
  25.                     System.out.println("value:" + test.getUserName());  
  26.                 }  
  27.             } else {  
  28.                 System.out.println("this is not  a field Annotation");  
  29.             }  
  30.   
  31.         } catch (Exception e) {  
  32.         }  
  33.   
  34.     }  
  35. }  
package com.test.www;


import java.lang.reflect.Field;

public class mainTest {

    public static void main(String[] args) {
        Test test = new Test();
        Class<Test> testClass = Test.class;
        try {
            //因爲是註解到Field上的,所以首先要獲取這個字段
            Field field = testClass.getDeclaredField("userName");

            //判斷這個Field上是否有這個註解
            if (field.isAnnotationPresent(FieldAnnotations.class)) {
                System.out.println("this is a field Annotation");

                //如果有這個註解,則獲取註解類
                FieldAnnotations fieldAnnotations = (FieldAnnotations) field.getAnnotation(FieldAnnotations.class);
                if (fieldAnnotations != null) {
                    //通過反射給私有變量賦值
                    field.setAccessible(true);
                    field.set(test, fieldAnnotations.value());
                    System.out.println("value:" + test.getUserName());
                }
            } else {
                System.out.println("this is not  a field Annotation");
            }

        } catch (Exception e) {
        }

    }
}

4. 輸出:

  1. this is a field Annotation  
  2. value:zhuli  
this is a field Annotation
value:zhuli

發佈了5 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章