首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2SE

Eclipse 3.1 深度體驗 J2SE 5.0 註解類型 (5):執行期反射動態查找註解完整實戰

     編輯:J2SE

核心 API:AnnotatedElement 介面

J2SE 5.0 在 java.lang.reflect 核心類別(Class、Method、Field、Constructor、Package)中引入 AnnotatedElement 介面,提供統一的註解查詢方法:

方法用途
isAnnotationPresent(Class<? extends Annotation>)判斷是否存在指定註解
getAnnotation(Class<T>)取得指定註解實例(含屬性值)
getAnnotations()取得所有註解(含繼承)
getDeclaredAnnotations()取得直接宣告的註解(不含繼承)

完整實戰範例:TODO 與 TOFORMAT 註解掃描器

1. 定義註解類型


// 方法級註解,含優先屬性
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TODO {
    int priority() default 0;
}

// 欄位級註解,標記需格式化
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TOFORMAT { }

2. 目標類別:MyCalculator


public class MyCalculator {
    boolean isReady;
    @TOFORMAT double concurrency;
    @TOFORMAT Date debitDate;

    @TODO(priority = 5)
    public void calculateRate() {
        System.out.println("Calculating...");
    }
}

3. 掃描器:TestCalculator


public class TestCalculator {
    public static void main(String[] args) {
        MyCalculator cal = new MyCalculator();
        cal.calculateRate(); // 正常業務邏輯

        try {
            Class<?> clazz = cal.getClass();

            // 掃描方法註解
            for (Method m : clazz.getDeclaredMethods()) {
                if (m.isAnnotationPresent(TODO.class)) {
                    TODO todo = m.getAnnotation(TODO.class);
                    System.out.println("Method: " + m.getName() 
                        + ", TODO present, priority=" + todo.priority());
                }
            }

            // 掃描欄位註解
            for (Field f : clazz.getDeclaredFields()) {
                if (f.isAnnotationPresent(TOFORMAT.class)) {
                    System.out.println("Field: " + f.getName() + ", TOFORMAT present");
                }
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

4. 執行結果

Calculating...
Method: calculateRate, TODO present, priority=5
Field: concurrency, TOFORMAT present
Field: debitDate, TOFORMAT present

Console 輸出結果

關鍵技術細節

  1. 保留策略決定可見性:@Retention(RUNTIME) 是執行期反射讀取的前提條件。若為 SOURCE 或 CLASS,執行期 isAnnotationPresent 永遠返回 false。
  2. getDeclaredMethods/Fields() 不含繼承:僅掃描該類別直接宣告的成員。需掃描繼承鏈請自行遞迴 getSuperclass()。
  3. 取得屬性值:m.getAnnotation(TODO.class).priority() 像呼叫普通方法一樣存取註解屬性。
  4. 預設值生效:未指定 priority 時自動為 0(編碼在註解類別的 default 子句)。

進階應用模式

模式關鍵註解掃描時機典型用途
編譯期代碼生成@GenerateBuilder, @EntityAPT / javac -processorLombok、MapStruct、JPA 實體增強
啟動期掃描裝配@Component, @AutowiredClasspath 掃描Spring、Guice 依賴注入
執行期攔截驗證@NotNull, @Valid方法呼叫攔截Bean Validation、AOP 參數檢查
文件/報表生成@Exportable, @ApiDoc按需觸發Swagger、自動化測試報告

Eclipse 3.1 開發支援

  • 註解屬性內容輔助:@TODO( 後按 Ctrl+Space 顯示 priority() 屬性。
  • Reflection API 智能提示:method. 列出 isAnnotationPresent、getAnnotation 等關鍵方法。
  • 快速修復缺失 @Retention:若註解未標 RUNTIME 卻嘗試反射讀取,Eclipse 可配置警告並一鍵添加。
  • 除錯視圖檢視註解:Variables 視圖中 Field/Method 物件可展開查看 annotations 陣列。

總結

執行期反射動態查找註解是「註解驅動開發」的基石。掌握 AnnotatedElement 四大查詢方法、務必加上 @Retention(RUNTIME)、善用 getAnnotation() 存取屬性值,即可構建靈活的掃描器、驗證器、生成器等工具。Eclipse 3.1 以智能提示與警告機制,將這套機制的正確使用內化為開發流程的自動防呆。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved