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

Java 註解保留策略:SOURCE、CLASS、RUNTIME 適用場景深度解析

     編輯:程式設計疑難解答

@Retention 三種策略對比

策略保留範圍類文件中是否存在運行時可否反射獲取典型用途
RetentionPolicy.SOURCE僅源碼階段否 (編譯器丟棄)否編譯時檢查、生成代碼、文檔生成
RetentionPolicy.CLASS編譯至類文件是否 (JVM 加載時丟棄)字節碼分析、註解處理器 (APT)、框架構建元數據
RetentionPolicy.RUNTIME運行時期是是依賴注入、ORM 映射、Web 路由、參數驗證、動態代理

詳細場景解析

1. SOURCE — 編譯期工具

特點:註解只存在於 .java 文件,javac 編譯時不寫入 .class。

核心用途:

  • @Override、@Deprecated、@SuppressWarnings — 編譯器內置處理。
  • Lombok:@Getter, @Builder 等,編譯期生成字節碼,運行時無痕跡。
  • 自定義編譯檢查:如 @NonNull 配合 Checker Framework 做靜態分析。
  • 文檔生成:Javadoc 讀取源碼註解生成 API 文檔。

2. CLASS — 字節碼分析 / APT

特點:寫入 .class 的 RuntimeInvisibleAnnotations 屬性表,JVM 類加載器不加載到內存,但字節碼分析工具 (ASM, Byte Buddy) 和註解處理器 (Annotation Processor) 可讀取。

核心用途:

  • 編譯時生成代碼:ButterKnife (舊版)、Dagger 2、Room、DataBinding — 註解處理器掃描 .class 生成輔助類。
  • 框架元數據收集:某些框架構建索引時只需類文件,無需啟動 JVM (構建速度快)。
  • 字節碼織入:AspectJ 編譯時織入 (CTW) 讀取 CLASS 保留註解決定切點。

3. RUNTIME — 反射驅動框架

特點:寫入 RuntimeVisibleAnnotations,JVM 加載類時解析到內存,Class.getAnnotations() 可獲取。

核心用途:

  • Spring 全家桶:@Autowired, @Component, @RequestMapping, @Transactional — 容器啟動掃描註解構建 BeanDefinition。
  • JPA/Hibernate:@Entity, @Table, @Column — 構建實體元數據模型。
  • JAX-RS / Spring MVC:@Path, @GET, @RequestBody — 運行時路由分發。
  • 參數驗證:@NotNull, @Size (Bean Validation) — 運行時攔截器反射檢查。
  • 動態代理 / AOP:掃描方法註解決定是否織入邏輯。

選擇決策流程圖

需要在運行時通過反射讀取?
  ├─ 是 → RUNTIME
  └─ 否
       需要在編譯時被註解處理器/字節碼工具讀取?
         ├─ 是 → CLASS
         └─ 否 → SOURCE (純文檀/編譯器提示)

組合使用最佳實踐

自定義註解可標註多個保留策略 (取最長);但通常明確指定一個。框架設計時:

  • 給用戶用的 API 註解 → RUNTIME (如 @MyService)。
  • 給構建工具用的註解 → CLASS (如 @GenerateBuilder)。
  • 給編碼規範用的註解 → SOURCE (如 @ThreadSafe)。

常見誤區

誤區:@Retention(RetentionPolicy.CLASS) 註解運行時能用反射讀到。
真相:不能。JVM 默認不加載 CLASS 保留註解。若需運行時讀取,必須用 RUNTIME。

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