Java自定義Annotation,通過反射解析Annotation

cd33 9年前發布 | 13K 次閱讀 Java Java開發

創建一個自定義的Annotation

import java.lang.annotation.*;
import java.lang.reflect.Method;

@Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MethodInfo { String author() default "hupeng"; String version() default "1.0"; String date(); String comment();

}</pre>

  • Annotation methods can’t have parameters.
  • Annotation methods return types are limited to primitives, String, Enums, Annotation or array of these.
  • Annotation methods can have default values.

@Target:

@Target說明了Annotation所修飾的對象范圍:Annotation可被用于 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循 環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標。

作用:用于描述注解的使用范圍(即:被描述的注解可以用在什么地方)

取值(ElementType)有:

1.CONSTRUCTOR:用于描述構造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部變量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述參數
7.TYPE:用于描述類、接口(包括注解類型) 或enum聲明

@Retention:

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

作用:表示需要在什么級別保存該注釋信息,用于描述注解的生命周期(即:被描述的注解在什么范圍內有效)

取值(RetentionPoicy)有:

1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)

@Documented:

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

@Inherited:

@Inherited 元注解是一個標記注解,@Inherited闡述了某個被標注的類型是被繼承的。,則這個annotation將被用于該class的子類。

注意:@Inherited annotation類型是被標注過的class的子類所繼承。類并不從它所實現的接口繼承annotation,方法并不從它所重載的方法繼承annotation。

Java 內置的Annotation

從java5版本開始,自帶了三種標準annontation類型,

  • Override,java.lang.Override 是一個marker annotation類型,它被用作標注方法。它說明了被標注的方法重載了父類的方法,起到了斷言的作用。如果我們使用了這種annotation在一個 沒有覆蓋父類方法的方法時,java編譯器將以一個編譯錯誤來警示。這個annotaton常常在我們試圖覆蓋父類方法而確又寫錯了方法名時加一個保障性 的校驗過程。
  • Deprecated,Deprecated也是一種marker annotation。,編譯器將不鼓勵使用這個被標注的程序元素。所以使用這種修飾具有一定的 “延續性”:如果我們在代碼中通過繼承或者覆蓋的方式使用了這個過時的類型或者成員,雖然繼承或者覆蓋后的類型或者成員并不是被聲明為 @Deprecated,但編譯器仍然要報警。注意:@Deprecated這個annotation類型和javadoc中的 @deprecated這個tag是有區別的:前者是java編譯器識別的,而后者是被javadoc工具所識別用來生成文檔(包含程序成員為什么已經過 時、它應當如何被禁止或者替代的描述)。
  • SuppressWarnings,此注解能告訴Java編譯器關閉對類、方法及成員變量的警告。有時編譯時會提出一些警告,對于這些警告有的隱 藏著Bug,有的是無法避免的,對于某些不想看到的警告信息,可以通過這個注解來屏蔽。SuppressWarning不是一個marker annotation。它有一個類型為String[]的成員,這個成員的值為被禁止的警告名。對于javac編譯器來講,,同時編譯器忽略掉無法識別的 警告名。

下面我們來使用Java內置的Annotation 和 自定義的Annotation

public class AnnotationExample {
    @Override
    @MethodInfo(author = "xxx",version = "1.0",date = "2015/03/26",comment = "override toString()")
    public String toString() {
        return "AnnotationExample{}";
    }

@Deprecated
@MethodInfo(comment = "deprecated method", date = "2015/03/26")
public static void oldMethod() {
    System.out.println("old method, don't use it.");
}

@SuppressWarnings({ "unchecked", "deprecation" })
@MethodInfo(author = "Pankaj", comment = "Main method", date = "Nov 17 2012", version = "1.0")
public static void genericsTest() {
    oldMethod();
}

}</pre>

使用反射來解析Annotation

注意我們的Annotation的Retention Policy 必須是RUNTIME,否則我們無法在運行時從他里面獲得任何數據。

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**

  • Created by Administrator on 2015/3/26. */ public class AnnotationParsing {

    public static void main(String[] args) {

     for (Method method: AnnotationExample.class.getMethods()) {
         if (method.isAnnotationPresent(MethodInfo.class)) {
             for (Annotation annotation:method.getAnnotations()) {
                 System.out.println(annotation + " in method:"+ method);
             }
    
             MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
    
             if ("1.0".equals(methodInfo.version())) {
                 System.out.println("Method with revision no 1.0 = "
                         + method);
             }
         }
     }
    

    } }</pre>  來源:縱酒揮刀斬人頭

 本文由用戶 cd33 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!