【 <二> 丹方改良:Spring 時代的 JavaWeb】之 Spring Boot 中的 AOP:實現日志記錄與性能監控

?<前文回顧>

點擊此處查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link

<今日更新>

一、開篇整活兒

今兒個咱嘮嘮 Spring Boot 里頭的 AOP(面向切面編程)。這玩意兒吧,說大不大,說小不小,整好了是錦上添花,整不好就是火上澆油。你要是剛入門,那可得悠著點兒,別一上來就整得自己“翻車”了。

二、AOP 是啥玩意兒?

AOP 是 Spring 里頭的一個高級特性,用來在不修改原有代碼的情況下,給程序動態添加功能。比如說,你可以用 AOP 來記錄日志、監控性能、處理異常啥的。Spring Boot 里頭默認就集成了這玩意兒,用起來賊方便。

1. AOP 的核心概念

AOP 里頭有幾個核心概念:切面(Aspect)、連接點(Join Point)、通知(Advice)、切點(Pointcut)。

  • 切面:就是你要添加的功能,比如說日志記錄、性能監控啥的。
  • 連接點:就是程序執行過程中的某個點,比如說方法調用、異常拋出啥的。
  • 通知:就是切面在連接點執行的動作,比如說在方法調用前記錄日志。
  • 切點:就是用來匹配連接點的表達式,比如說匹配某個包下的所有方法。

2. AOP 的通知類型

AOP 里頭有五種通知類型:

  • 前置通知(Before):在連接點之前執行。
  • 后置通知(After):在連接點之后執行,不管連接點是否拋出異常。
  • 返回通知(AfterReturning):在連接點正常返回后執行。
  • 異常通知(AfterThrowing):在連接點拋出異常后執行。
  • 環繞通知(Around):在連接點前后都執行,可以控制連接點的執行。

三、用 AOP 實現日志記錄

日志記錄是 AOP 的經典應用場景。你可以用 AOP 來記錄方法的調用信息,方便以后排查問題。

1. 定義切面

首先,你得定義一個切面,用?@Aspect?注解標記。

Java Code

@Aspect

@Component

public class LoggingAspect {

????private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

}

這段代碼里頭,LoggingAspect?是一個切面,@Aspect?注解標記了這個類,@Component?注解讓 Spring 管理這個類。

2. 定義切點

然后,你得定義一個切點,用?@Pointcut?注解標記。

Java Code

@Aspect

@Component

public class LoggingAspect {

????private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

????@Pointcut("execution(* com.example.demo.service.*.*(..))")

????public void serviceMethods() {}

}

這段代碼里頭,serviceMethods?是一個切點,execution(* com.example.demo.service.*.*(..))?表示匹配?com.example.demo.service?包下的所有方法。

3. 定義通知

最后,你得定義通知,用?@Before、@After、@AfterReturning、@AfterThrowing?或?@Around?注解標記。

Java Code

@Aspect

@Component

public class LoggingAspect {

????private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

????@Pointcut("execution(* com.example.demo.service.*.*(..))")

????public void serviceMethods() {}

????@Before("serviceMethods()")

????public void logMethodCall(JoinPoint joinPoint) {

????????logger.info("調用方法:{}", joinPoint.getSignature().getName());

????}

}

這段代碼里頭,logMethodCall?是一個前置通知,@Before?注解標記了這個方法,JoinPoint?參數用來獲取連接點的信息。

四、用 AOP 實現性能監控

性能監控是 AOP 的另一個經典應用場景。你可以用 AOP 來記錄方法的執行時間,方便以后優化性能。

1. 定義切面

首先,你得定義一個切面,用?@Aspect?注解標記。

Java Code

@Aspect

@Component

public class PerformanceAspect {

????private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

}

這段代碼里頭,PerformanceAspect?是一個切面,@Aspect?注解標記了這個類,@Component?注解讓 Spring 管理這個類。

2. 定義切點

然后,你得定義一個切點,用?@Pointcut?注解標記。

Java Code

@Aspect

@Component

public class PerformanceAspect {

????private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

????@Pointcut("execution(* com.example.demo.service.*.*(..))")

????public void serviceMethods() {}

}

這段代碼里頭,serviceMethods?是一個切點,execution(* com.example.demo.service.*.*(..))?表示匹配?com.example.demo.service?包下的所有方法。

3. 定義通知

最后,你得定義通知,用?@Around?注解標記。

Java Code

@Aspect

@Component

public class PerformanceAspect {

????private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

????@Pointcut("execution(* com.example.demo.service.*.*(..))")

????public void serviceMethods() {}

????@Around("serviceMethods()")

????public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

????????long startTime = System.currentTimeMillis();

????????Object result = joinPoint.proceed();

????????long endTime = System.currentTimeMillis();

????????logger.info("方法 {} 執行時間:{} 毫秒", joinPoint.getSignature().getName(), endTime - startTime);

????????return result;

????}

}

這段代碼里頭,measureMethodExecutionTime?是一個環繞通知,@Around?注解標記了這個方法,ProceedingJoinPoint?參數用來控制連接點的執行。

五、AOP 的坑點

1. 切點表達式寫錯了

AOP 里頭,切點表達式寫錯了,那通知就不起作用了。你要是寫錯了,那可得好好檢查檢查。

Java Code

@Pointcut("execution(* com.example.demo.service.*.*(..))") // 寫錯了

public void serviceMethods() {}

這段代碼里頭,execution?寫錯了,應該是?execution。

當然,寫不好表達式,可以問AI啊。

2. 通知順序不對

AOP 里頭,通知順序不對,那結果就不對了。你要是順序不對,那可得好好調整調整。

Java Code

@Before("serviceMethods()")

public void logMethodCall(JoinPoint joinPoint) {

????logger.info("調用方法:{}", joinPoint.getSignature().getName());

}

@Around("serviceMethods()")

public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

????long startTime = System.currentTimeMillis();

????Object result = joinPoint.proceed();

????long endTime = System.currentTimeMillis();

????logger.info("方法 {} 執行時間:{} 毫秒", joinPoint.getSignature().getName(), endTime - startTime);

????return result;

}

這段代碼里頭,logMethodCall?和?measureMethodExecutionTime?的順序很重要。

3. 切面沒被 Spring 管理

AOP 里頭,切面沒被 Spring 管理,那通知就不起作用了。你要是沒被管理,那可得好好檢查檢查。

Java Code

@Aspect // 沒加 @Component

public class LoggingAspect {

????private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

????@Pointcut("execution(* com.example.demo.service.*.*(..))")

????public void serviceMethods() {}

????@Before("serviceMethods()")

????public void logMethodCall(JoinPoint joinPoint) {

????????logger.info("調用方法:{}", joinPoint.getSignature().getName());

????}

}

這段代碼里頭,LoggingAspect?沒加?@Component?注解,Spring 不會管理這個類。

、額外再說一點

對于大多數 Spring Boot 項目,如果你只是簡單地使用 AOP 來實現日志記錄、事務管理等功能,并且已經引入了?spring-boot-starter-aop?依賴,那么通常不需要顯式地使用?@EnableAspectJAutoProxy?注解。Spring Boot 會自動為你處理相關的配置。

然而,如果你有特殊的需求,比如自定義代理創建策略或確保 AOP 支持被啟用,那么你可以考慮顯式地使用?@EnableAspectJAutoProxy?注解

專有名詞解釋

  1. AOP:面向切面編程,一種編程范式,用來在不修改原有代碼的情況下,給程序動態添加功能。
  2. 切面:AOP 里頭的一個概念,表示你要添加的功能。
  3. 連接點:AOP 里頭的一個概念,表示程序執行過程中的某個點。
  4. 通知:AOP 里頭的一個概念,表示切面在連接點執行的動作。
  5. 切點:AOP 里頭的一個概念,表示用來匹配連接點的表達式。
  6. 前置通知:AOP 里頭的一種通知類型,在連接點之前執行。
  7. 后置通知:AOP 里頭的一種通知類型,在連接點之后執行。
  8. 返回通知:AOP 里頭的一種通知類型,在連接點正常返回后執行。
  9. 異常通知:AOP 里頭的一種通知類型,在連接點拋出異常后執行。
  10. 環繞通知:AOP 里頭的一種通知類型,在連接點前后都執行。
  11. JoinPoint:AOP 里頭的一個接口,用來獲取連接點的信息。
  12. ProceedingJoinPoint:AOP 里頭的一個接口,用來控制連接點的執行。

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

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

相關文章

TCP/IP協議簇

文章目錄 應用層http/httpsDNS補充 傳輸層TCP1. 序列號與確認機制2. 超時重傳3. 流量控制&#xff08;滑動窗口機制&#xff09;4. 擁塞控制5. 錯誤檢測與校驗6. 連接管理總結 網絡層ARP**ARP 的核心功能**ARP 的工作流程1. ARP 請求&#xff08;Broadcast&#xff09;2. ARP 緩…

SpringBoot分布式項目訂單管理實戰:Mybatis最佳實踐全解

一、架構設計與技術選型 典型分布式訂單系統架構&#xff1a; [網關層] → [訂單服務] ←→ [分布式緩存]↑ ↓ [用戶服務] [支付服務]↓ ↓ [MySQL集群] ← [分庫分表中間件]技術棧組合&#xff1a; Spring Boot 3.xMybatis-Plus 3.5.xShardingSpher…

微服務架構中的精妙設計:環境和工程搭建

一.前期準備 1.1開發環境安裝 Oracle從JDK9開始每半年發布?個新版本, 新版本發布后, ?版本就不再進?維護. 但是會有?個?期維護的版本. ?前?期維護的版本有: JDK8, JDK11, JDK17, JDK21 在 JDK版本的選擇上&#xff0c;盡量選擇?期維護的版本. 為什么選擇JDK17? S…

Maven 構建配置文件詳解

Maven 構建配置文件詳解 引言 Maven 是一個強大的項目管理和構建自動化工具,廣泛應用于 Java 開發領域。在 Maven 項目中,配置文件扮演著至關重要的角色。本文將詳細介紹 Maven 構建配置文件的相關知識,包括配置文件的作用、結構、配置方法等,幫助讀者更好地理解和應用 M…

【YOLO系列】基于YOLOv8的無人機野生動物檢測

基于YOLOv8的無人機野生動物檢測 1.前言 在野生動物保護、生態研究和環境監測領域&#xff0c;及時、準確地檢測和識別野生動物對于保護生物多樣性、預防人類與野生動物的沖突以及制定科學的保護策略至關重要。傳統的野生動物監測方法通常依賴于地面巡邏、固定攝像頭或無線傳…

Hive UDF開發實戰:構建高性能JSON生成器

目錄 一、背景與需求場景 二、開發環境準備 2.1 基礎工具棧 2.2 Maven依賴配置 三、核心代碼實現

分布式特性對比

以下是關于 分片(Sharding)、一致性哈希、兩階段提交(2PC)、Paxos、Raft協議、數據局部性 的對比分析與關聯性總結,涵蓋核心機制、適用場景及相互關系: 一、概念對比與關聯 概念核心目標關鍵特性典型應用場景與其它技術的關聯分片(Sharding)數據水平拆分按規則(哈希、…

歷史分鐘高頻數據

外盤期貨高頻分鐘歷史回測行情數據下載 鏈接: https://pan.baidu.com/s/1RUbAMxfiSyBlXfrwT_0n2w?pwdhgya 提取碼: hgya通過美國期貨高頻交易所歷史行情可以看到很多細節比如品種之一&#xff1a;FGBX_1min (1)在2024-02-29 11:14:00關鍵交易時刻&#xff0c;一筆大規模訂單突…

final+模版設計模式的理解

模板設計模式在 Java 里是一種行為設計模式&#xff0c;它在抽象類里定義算法的骨架&#xff0c;把部分步驟的具體實現延遲到子類。如此一來&#xff0c;子類可以在不改變算法結構的基礎上&#xff0c;重新定義算法中的特定步驟。 模式組成 抽象類&#xff08;Abstract Class…

JAVA接口調用限速器

目錄 1、并發限速 2、串行限速 需求&#xff1a;批量調用第三方ERP接口&#xff0c;對方接口限流時&#xff0c;減緩調用速率。 1、并發限速 Slf4j RestController public class ApiCallTask {//第三方接口Resourceprivate ErpService erpService;//異步線程池Resourcepriv…

STM32 CAN控制器硬件資源與用法

1、硬件結構圖 以STM32F4為例&#xff0c;他有2個can控制器&#xff0c;分別為 CAN1 CAN2。 每個CAN控制器&#xff0c;都有3個發送郵箱、2個接收fifo&#xff0c;每個接收fifo又由3個接收郵箱組成。也即每個CAN控制器都有9個郵箱&#xff0c;其中3個供發送用&#xff0c;3個…

【C++ 繼承】—— 青花分水、和而不同,繼承中的“明明德”與“止于至善”

歡迎來到ZyyOvO的博客?&#xff0c;一個關于探索技術的角落&#xff0c;記錄學習的點滴&#x1f4d6;&#xff0c;分享實用的技巧&#x1f6e0;?&#xff0c;偶爾還有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原創??&#xff0c;感謝支持??&#xff01;請尊重原創&#x1…

Qt warning LNK4042: 對象被多次指定;已忽略多余的指定

一、常規原因&#xff1a; pro或pri 文件中源文件被多次包含 解決&#xff1a;刪除變量 SOURCES 和 HEADERS 中重復條目 二、誤用 對于某些pri庫可以使用如下代碼簡寫包含 INCLUDEPATH $$PWDHEADERS $$PWD/*.hSOURCES $$PWD/*.cpp但是假如該目錄下只有頭文件&#xff0c;沒…

Visual Studio Code 無法打開源文件解決方法

&#x1f308; 個人主頁&#xff1a;Zfox_ &#x1f525; 系列專欄&#xff1a;Linux &#x1f525; 系列專欄&#xff1a;C從入門到精通 目錄 一&#xff1a;&#x1f525; 突發狀況 二&#xff1a;&#x1f525; 共勉 一&#xff1a;&#x1f525; 突發狀況 &#x1f42c;…

js文字兩端對齊

目錄 一、問題 二、原因及解決方法 三、總結 一、問題 1.text-align: justify; 不就可以了嗎&#xff1f;但是實際測試無效 二、原因及解決方法 1.原因&#xff1a;text-align只對非最后一行文字有效。只有一行文字時&#xff0c;text-align無效&#xff0c;要用text-alig…

LeetCode算法題(Go語言實現)_20

題目 給你兩個下標從 0 開始的整數數組 nums1 和 nums2 &#xff0c;請你返回一個長度為 2 的列表 answer &#xff0c;其中&#xff1a; answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整數組成的列表。 answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整數組成…

每天認識一個設計模式-橋接模式:在抽象與實現的平行宇宙架起彩虹橋

一、前言&#xff1a;虛擬機橋接的啟示 使用過VMware或者Docker的同學們應該都接觸過網絡橋接&#xff0c;在虛擬機網絡配置里&#xff0c;橋接模式是常用的網絡連接方式。選擇橋接模式時&#xff0c;虛擬機會通過虛擬交換機與物理網卡相連&#xff0c;獲取同網段 IP 地址&…

java筆記02

運算符 1.隱式轉換和強制轉換 類型轉換的分類 1.隱式轉換&#xff1a; 取值范圍小的數值 轉換為 取值范圍大的數值 2.強制轉換&#xff1a; 取值范圍大的數值 轉換為 取值范圍小的數值隱式轉換的兩種提升規則 取值范圍小的&#xff0c;和取值范圍大的進行運算&#xff0c;小的…

Redis-07.Redis常用命令-集合操作命令

一.集合操作命令 SADD key member1 [member2]&#xff1a; sadd set1 a b c d sadd set1 a 0表示沒有添加成功&#xff0c;因為集合中已經有了這個元素了&#xff0c;因此無法重復添加。 SMEMBERS key: smembers set1 SCARD key&#xff1a; scard set1 SADD key member1 …

李飛飛、吳佳俊團隊新作:FlowMo如何以零卷積、零對抗損失實現ImageNet重構新巔峰

目錄 一、摘要 二、引言 三、相關工作 四、方法 基于擴散先前的離散標記化器利用廣告 架構 階段 1A&#xff1a;模式匹配預訓練 階段 1B&#xff1a;模式搜索后訓練 采樣 第二階段&#xff1a;潛在生成建模 五、Coovally AI模型訓練與應用平臺 六、實驗 主要結果 …