【Java】Java元注解

@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OperatorLog {String source() default "WEB"; //日志操作來源 默認是web,還有socket的String model() default ""; //操作模塊
}

這個代碼中的 @Target@Retention元注解(meta-annotations),它們用于指定自定義注解的使用規則和行為。元注解本身并不直接影響注解的功能,而是控制注解如何被應用和如何被處理。

元注解解析:

  1. @Target

    • 作用:指定自定義注解可以應用于哪些程序元素。常見的元素類型有:
      • ElementType.METHOD:表示該注解只能應用于方法。
      • ElementType.TYPE:表示該注解可以應用于類、接口、枚舉等類型。
      • ElementType.FIELD:表示該注解可以應用于字段。
      • ElementType.PARAMETER:表示該注解可以應用于方法參數。
      • ElementType.LOCAL_VARIABLE:表示該注解可以應用于局部變量。
      • ElementType.CONSTRUCTOR:表示該注解可以應用于構造函數。
      • ElementType.ANNOTATION_TYPE:表示該注解可以應用于其他注解。
      • ElementType.PACKAGE:表示該注解可以應用于包。

    在你的代碼中,@Target(ElementType.METHOD) 表示 OperatorLog 注解只能應用于方法上。也就是說,你不能將該注解應用于字段或類上。

  2. @Retention

    • 作用:指定注解在什么時機可用。常見的保留策略有:
      • RetentionPolicy.SOURCE:注解僅存在于源代碼中,編譯后會被丟棄。
      • RetentionPolicy.CLASS:注解會被編譯器保留在 .class 文件中,但在運行時不可用(默認行為)。
      • RetentionPolicy.RUNTIME:注解會被編譯并保留在 .class 文件中,運行時可通過反射讀取。通常自定義注解都使用 RUNTIME 保留策略,便于在運行時進行處理。

    在你的代碼中,@Retention(value = RetentionPolicy.RUNTIME) 表示 OperatorLog 注解在運行時依然可用,可以通過反射來訪問。

總結即為:

  • @Target 用來指定注解應用的場景,通常需要使用它來限制注解的應用范圍。
  • @Retention 用來指定注解的生命周期,通常也需要使用它來確保注解在編譯后仍然可以被訪問(例如通過反射)。
  • 其他元注解:除了 @Target@Retention,Java 還提供了其他元注解,如:
    • @Documented:表示該注解會出現在 Javadoc 中,適用于文檔化注解。
    • @Inherited:表示該注解可以被子類繼承(僅對類注解有效)。
    • @Conditional(HAEnabledCheck.class)這是核心的元注解,表示 @HaEnabled 注解的啟用依賴于條件判斷。@Conditional 注解接收一個類(這里是 HAEnabledCheck)作為參數,只有當這個類的判斷條件為 true 時,@HaEnabled 注解才會生效。
      HAEnabledCheck 是一個條件類,通常是一個實現了 Condition 接口的類,它決定是否啟用帶有 @HaEnabled 注解的功能。

如果你希望在自定義注解上使用反射,或者限制注解應用的范圍,就需要使用這些元注解。

注解和反射

在Java中,“在注解上使用反射”指的是通過反射機制在運行時動態地讀取和處理注解的內容。反射是一種在程序運行時檢查和操作類、方法、字段等的能力,而注解是一種用于在代碼中添加元數據的機制。

反射和注解的關系

注解本身只是對代碼的標記,它不會自動執行某些操作,反而需要程序在運行時通過反射去讀取它,基于注解的信息做一些邏輯上的處理。例如,AOP(面向切面編程)就是通過反射讀取注解,來決定是否在方法執行前、后或者拋出異常時執行某些邏輯。

如何通過反射讀取注解

  1. 定義注解
    首先,你需要定義一個注解,并在注解上使用元注解(如 @Target, @Retention)來指定注解的使用規則和生命周期。

    示例:

    @Retention(RetentionPolicy.RUNTIME)  // 保留到運行時
    @Target(ElementType.METHOD)         // 只允許用于方法
    public @interface MyAnnotation {String value() default "defaultValue";  // 注解中的屬性
    }
    
  2. 在代碼中使用注解
    然后,你可以在代碼中的方法上使用該注解,來標記某些方法。

    示例:

    public class MyClass {@MyAnnotation(value = "Hello, World!")public void myMethod() {System.out.println("Executing myMethod...");}
    }
    
  3. 通過反射讀取注解
    接下來,通過反射,你可以獲取方法上的注解信息,并根據注解的內容來執行相應的操作。為了讀取注解,你可以使用 Method 類的 getAnnotation 方法。

    示例:

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;public class AnnotationExample {public static void main(String[] args) throws Exception {// 獲取 MyClass 類的字節碼對象Class<MyClass> clazz = MyClass.class;// 獲取 myMethod 方法的 Method 對象Method method = clazz.getMethod("myMethod");// 檢查該方法是否有 MyAnnotation 注解if (method.isAnnotationPresent(MyAnnotation.class)) {// 獲取 MyAnnotation 注解MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);// 讀取注解中的值System.out.println("Annotation value: " + annotation.value());}// 執行方法MyClass obj = new MyClass();obj.myMethod();}
    }
    
  4. 運行結果
    在運行時,程序會讀取 myMethod 上的 MyAnnotation 注解,并輸出注解中的 value 屬性內容,執行結果如下:

    Annotation value: Hello, World!
    Executing myMethod...
    

為什么需要在注解上使用反射?

反射與注解的結合非常強大,它能夠讓你在程序運行時根據注解的內容動態地改變程序行為,這就是所謂的“注解驅動編程”。

常見的應用場景有:

  1. AOP(面向切面編程)
    使用注解標記方法,然后通過反射獲取注解的值,執行一些邏輯(如日志、權限檢查、事務控制等)對方法進行增強。比如Spring中的@Transactional注解,使用反射來判斷方法是否需要事務支持。

    @Transactional
    public void someMethod() {// 業務邏輯
    }
    
  2. 依賴注入(DI)
    在Spring等框架中,通過注解(如 @Autowired@Inject)標記字段或方法,框架通過反射讀取這些注解并自動注入依賴。

    @Autowired
    private MyService myService;
    
  3. ORM(對象關系映射)框架
    在ORM框架中,注解可以標記實體類與數據庫表的映射關系,框架通過反射讀取注解,在數據庫中進行查詢、插入等操作。

    @Entity
    public class User {@Idprivate Long id;private String name;
    }
    
  4. 自定義注解的處理
    可以創建自定義注解,并結合反射來控制程序的行為。例如,創建一個注解用于記錄日志,或者控制某個方法的訪問權限等。

小結:

“在注解上使用反射”就是通過反射機制,在程序運行時,動態地獲取注解的值,并基于這些值來執行一些操作。反射提供了靈活的動態行為,注解則提供了豐富的元數據支持,兩者結合能夠實現很多靈活的功能,例如日志記錄、事務管理、權限控制等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84181.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84181.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84181.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

阿里云百煉(1) : 阿里云百煉應用問答_回答圖片問題_方案1_提問時上傳圖片文件

直接用于拍照答題不大理想, 可能適用其他用途, 更好的方案: 阿里云百煉(1) : 阿里云百煉應用問答_回答圖片問題_方案2_提取題目再提問-CSDN博客 1.實現代碼 package cn.nordrassil.ly.test.拍照答題;import com.alibaba.dashscope.app.Application; import com.alibaba.dashsc…

深入探索 CSS 中的偽類:從基礎到實戰?

在前端開發的世界里&#xff0c;CSS 作為網頁樣式的 “化妝師”&#xff0c;有著至關重要的作用。而 CSS 偽類則像是這位 “化妝師” 手中的神奇畫筆&#xff0c;能夠基于元素的狀態或位置為其添加獨特的樣式&#xff0c;極大地豐富了網頁的交互性和視覺效果。接下來&#xff0…

c++ constexpr關鍵字

constexpr字面意思為常量表格式&#xff0c; 用于指示編譯器在編譯時計算表達式的值。 1、作為常量表格式&#xff0c;必須在編譯時就能確定其值。如&#xff1a;constexpr int size 9527; 2、可以修飾函數&#xff0c;要求能在編譯時求值&#xff0c;所以傳的參數也必須是編…

服務器硬盤分類

以下是服務器硬盤的綜合性分類與技術特性分析&#xff0c;依據當前行業標準及技術演進整理&#xff1a; 一、按存儲介質分類 1. ?機械硬盤&#xff08;HDD&#xff09;? ? 核心特性?&#xff1a;采用旋轉磁盤與機械磁頭結構&#xff0c;通過磁道尋址實現數據讀寫 …

圖解深度學習 - 機器學習簡史

前言 深度學習并非總是解決問題的最佳方案&#xff1a;缺乏足夠數據時&#xff0c;深度學習難以施展&#xff1b;某些情況下&#xff0c;其他機器學習算法可能更為高效。 若初學者首次接觸的是深度學習&#xff0c;可能會形成一種偏見&#xff0c;視所有機器學習問題為深度學…

ConceptAttention:Diffusion Transformers learn highly interpretable features

ConceptAttention: Diffusion Transformers Learn Highly Interpretable Featureshttps://arxiv.org/html/2502.04320?_immersive_translate_auto_translate=1用flux的attention來做圖文的顯著性分析。 1.i

【Python正則表達式終極指南】從零到工程級實戰

目錄 &#x1f31f; 前言&#x1f3d7;? 技術背景與價值&#x1fa79; 當前技術痛點&#x1f6e0;? 解決方案概述&#x1f465; 目標讀者說明 &#x1f9e0; 一、技術原理剖析&#x1f4ca; 核心概念圖解&#x1f4a1; 核心作用講解&#x1f527; 關鍵技術模塊說明?? 技術選…

C++對象的內存模型

C++對象的內存模型涉及對象的數據成員(包括靜態成員和非靜態成員)、成員函數以及虛函數表等在內存中的布局和管理方式。以下是C++對象的內存模型的主要組成部分: 1. C++對象的組成 一個C++對象通常由以下幾個部分組成: 非靜態數據成員 對象的核心組成部分,每個對象都有自己…

hugging-face數據集快速下載

開發機配置外網代理并使用 git lfs 高速下載 Hugging Face 數據集流程 本文檔將介紹如何配置開發機的代理&#xff0c;登錄 Hugging Face&#xff0c;并使用 git-lfs &#xff08;Git Large File Storage&#xff09;進行數據集的高速下載。 1. 配置代理連接外網 開發機在某些…

17、Python對象操作全解析:同一運算符、成員運算符與整數緩存機制實戰

適合人群&#xff1a;零基礎自學者 | 編程小白快速入門 閱讀時長&#xff1a;約8分鐘 文章目錄 一、問題&#xff1a;Python 同一運算符的本質與實戰&#xff1f;1、例子1&#xff1a;雙胞胎身份證驗證2、答案&#xff1a;&#xff08;1&#xff09;is 同一運算符介紹&#xff…

使用auto-coder將kotti項目的pyramid依賴從1.x升級到2.x,將SQLALchemy從1.x升級到2.x

緣起 kotti是一個非常好的基于pyramid框架的web搭建項目&#xff0c;但是由于作者離世&#xff0c;已經3年沒有更新了。 嘗試使用auto-coder將kotti項目的pyramid依賴從1.x升級到2.x&#xff0c;同時發現SQLALchemy依賴也有問題&#xff0c;將SQLALchemy從1.x升級到2.x 開始…

luckysheet的使用——17.將表格作為pdf下載到本地

luckysheet源碼里面自帶有打印按鈕&#xff0c;但是功能是無法使用的&#xff0c;所以我把該功能重寫了一遍 1.在menuButton.js文件中找到源碼打印按鈕的觸發事件&#xff1a; $("#luckysheet-icon-print").click(function () {}2.使用自己寫的掛載方法 window.pr…

仿真APP助力提升卡車駕駛室駕乘舒適度與安全性

駕駛室作為卡車的重要組成部分&#xff0c;其振動特性對于駕駛員的舒適度和長期健康具有至關重要的影響。振動不僅會導致駕駛員疲勞、分散注意力&#xff0c;還可能引發一系列健康問題。為了確保卡車在復雜路面工況下駕駛室結構不受破壞&#xff0c;并保持良好的NVH性能&#x…

功能強大且易于使用的 JavaScript 音頻庫howler.js 和AI里如何同時文字跟音頻構思想法

howler.js 是一個功能強大且易于使用的 JavaScript 音頻庫&#xff0c;它提供了跨瀏覽器的音頻播放功能&#xff0c;支持多種音頻格式&#xff0c;并且具有豐富的 API&#xff0c;可以方便地控制音頻的播放、暫停、循環、音量等。下面是如何在 Vue 項目中使用 howler.js 實現音…

JUC入門(七)

14、ForkJoin ForkJoin框架是Java中用于并行執行任務的框架&#xff0c;特別適合處理可以分解為多個子任務的復雜計算。它基于“分而治之”的思想&#xff0c;將一個大任務分解為多個小任務&#xff0c;這些小任務可以并行執行&#xff0c;最后將結果合并。 ForkJoin框架的核…

第 7 章:綜合回顧與性能優化

本章目標: 系統化地回顧各類外設接口選型原則 深入探討多接口并存時的資源沖突與管理策略 掌握軟硬件協同的性能分析方法,快速定位并消除瓶頸 總結一整套從架構設計到現場調試的最佳實踐與防坑指南 7.1 綜合選型決策矩陣(深度分析) 除了前文的基礎矩陣,這里引入兩個更細化…

交換機的連接方式堆疊和級聯

以下是交換機的堆疊和級聯各自的優缺點總結&#xff0c;幫助快速對比選擇&#xff1a; ?一、堆疊&#xff08;Stacking&#xff09;? ?優點 ?高性能 堆疊鏈路帶寬高&#xff08;如10G/40G/100G&#xff09;&#xff0c;成員間數據通過背板直連&#xff0c;無帶寬瓶頸。支…

C++高效求解非線性方程組的實踐指南

非線性方程組的求解是科學與工程計算中的核心問題之一&#xff0c;涉及物理建模、機器學習、金融分析等多個領域。C因其高性能和底層控制能力成為此類問題的首選語言&#xff0c;但如何高效實現求解仍存在諸多挑戰。本文從算法選擇、工具應用、穩定性優化及性能提升四個維度&am…

2025年- H42-Lc150 --146. LRU緩存(哈希表,雙鏈表)需二刷--Java版

1.題目描述 2.思路 LRU(最近最少使用&#xff09;&#xff1a;如果緩存的容量為2&#xff0c;剛開始的兩個元素都入棧。之后該2元素中有其中一個元素&#xff08;重點元素&#xff09;被訪問。把最近訪問過的重點元素保留&#xff0c;另一個邊緣元素就得離開緩存了。 下面是l…

5G 網絡中 DNN 的深度解析:從基礎概念到核心應用

摘要 本文深度剖析 5G 網絡中 DNN(數據網絡名稱)的核心作用與運行機制,從基礎概念入手,詳細闡述 DNN 在會話管理、用戶面資源分配、切片選擇等方面的關鍵功能。通過實際應用場景分析與技術實現細節探討,揭示 DNN 如何助力 5G 網絡滿足多樣化業務需求,為 5G 網絡部署、優…