Spring AOP 典型應用場景

AOP 典型應用場景

      • 1. 日志記錄(Logging)
        • 代碼實現
      • 2. 權限校驗(Authentication)
        • 代碼實現
      • 3. 性能監控(Performance Monitoring)
        • 代碼實現
      • 4. 緩存處理(Caching)
        • 代碼實現
      • 5. 重試機制(Retry)
        • 代碼實現
      • 6. 事務管理(Transaction Management)
        • 代碼實現
      • 7. 接口限流(Rate Limiting)
        • 代碼實現
      • 總結表格

在這里插入圖片描述

1. 日志記錄(Logging)

場景:自動記錄方法的入參、返回值、執行時間和異常信息。

代碼實現

1. 自定義日志注解

// annotation/Loggable.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {String tag() default "DEFAULT";
}

2. 切面邏輯

// aop/LoggingAspect.java
@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Around("@annotation(loggable)")public Object logMethod(ProceedingJoinPoint pjp, Loggable loggable) throws Throwable {String methodName = pjp.getSignature().getName();String className = pjp.getTarget().getClass().getSimpleName();String tag = loggable.tag();// 記錄方法開始logger.info("[{}] {}.{}() 入參: {}", tag, className, methodName, Arrays.toString(pjp.getArgs()));long startTime = System.currentTimeMillis();try {Object result = pjp.proceed();long duration = System.currentTimeMillis() - startTime;// 記錄方法結束logger.info("[{}] {}.{}() 耗時: {}ms 返回: {}", tag, className, methodName, duration, result);return result;} catch (Exception e) {// 記錄異常logger.error("[{}] {}.{}() 異常: {}", tag, className, methodName, e.getMessage(), e);throw e;}}
}

3. 業務類使用

// service/UserService.java
@Service
public class UserService {@Loggable(tag = "USER-SERVICE")public String getUserById(Long id) {return "User-" + id; // 模擬數據庫查詢}
}

4. 測試運行

// MainApp.java
public class MainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);userService.getUserById(123L);context.close();}
}

輸出結果

[USER-SERVICE] UserService.getUserById() 入參: [123]
[USER-SERVICE] UserService.getUserById() 耗時: 2ms 返回: User-123

2. 權限校驗(Authentication)

場景:驗證用戶是否具有訪問特定方法的權限。

代碼實現

1. 自定義權限注解

// annotation/RequireRole.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireRole {String value() default "USER";
}

2. 切面邏輯

// aop/SecurityAspect.java
@Aspect
@Component
public class SecurityAspect {// 模擬當前用戶角色private String currentUserRole = "ADMIN";@Before("@annotation(requireRole)")public void checkPermission(JoinPoint jp, RequireRole requireRole) {String requiredRole = requireRole.value();if (!requiredRole.equals(currentUserRole)) {throw new SecurityException("權限不足! 需要角色: " + requiredRole);}}
}

3. 業務類使用

// service/AdminService.java
@Service
public class AdminService {@RequireRole("ADMIN")public void deleteDatabase() {System.out.println("數據庫已刪除!"); // 危險操作}
}

4. 測試運行

public class MainApp {public static void main(String[] args) {try {AdminService adminService = context.getBean(AdminService.class);adminService.deleteDatabase();} catch (Exception e) {System.out.println("錯誤: " + e.getMessage());}}
}

輸出結果

數據庫已刪除!  // 如果currentUserRole="ADMIN"
錯誤: 權限不足! 需要角色: ADMIN  // 如果currentUserRole="USER"

3. 性能監控(Performance Monitoring)

場景:統計方法執行耗時,用于性能分析。

代碼實現

1. 切面邏輯

// aop/PerformanceAspect.java
@Aspect
@Component
public class PerformanceAspect {@Around("execution(* com.example.service.*.*(..))")public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {long start = System.currentTimeMillis();Object result = pjp.proceed();long duration = System.currentTimeMillis() - start;String methodName = pjp.getSignature().getName();System.out.println("方法 " + methodName + " 執行耗時: " + duration + "ms");return result;}
}

2. 業務類

// service/DataProcessor.java
@Service
public class DataProcessor {public void process() throws InterruptedException {Thread.sleep(500); // 模擬耗時操作}
}

3. 測試輸出

方法 process 執行耗時: 503ms

4. 緩存處理(Caching)

場景:緩存方法返回值,減少重復計算。

代碼實現

1. 自定義緩存注解

// annotation/Cacheable.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {String keyPrefix() default "";int ttl() default 300; // 緩存時間(秒)
}

2. 切面邏輯

// aop/CacheAspect.java
@Aspect
@Component
public class CacheAspect {private Map<String, Object> cache = new ConcurrentHashMap<>();@Around("@annotation(cacheable)")public Object handleCache(ProceedingJoinPoint pjp, Cacheable cacheable) throws Throwable {String key = cacheable.keyPrefix() + Arrays.toString(pjp.getArgs());if (cache.containsKey(key)) {System.out.println("從緩存獲取數據: " + key);return cache.get(key);}Object result = pjp.proceed();cache.put(key, result);System.out.println("將數據存入緩存: " + key);return result;}
}

3. 業務類使用

// service/ProductService.java
@Service
public class ProductService {@Cacheable(keyPrefix = "product:")public String getProductInfo(String productId) {System.out.println("實際查詢數據庫...");return "Info-" + productId;}
}

4. 測試結果

productService.getProductInfo("P100"); // 輸出: 實際查詢數據庫... 將數據存入緩存: product:[P100]
productService.getProductInfo("P100"); // 輸出: 從緩存獲取數據: product:[P100]

5. 重試機制(Retry)

場景:在方法執行失敗時自動重試。

代碼實現

1. 自定義重試注解

// annotation/Retry.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {int maxAttempts() default 3;
}

2. 切面邏輯

// aop/RetryAspect.java
@Aspect
@Component
public class RetryAspect {@Around("@annotation(retry)")public Object retryOperation(ProceedingJoinPoint pjp, Retry retry) throws Throwable {int attempts = 0;Exception lastException;do {attempts++;try {return pjp.proceed();} catch (Exception e) {lastException = e;System.out.println("第 " + attempts + " 次嘗試失敗");}} while (attempts < retry.maxAttempts());throw lastException;}
}

3. 業務類使用

// service/PaymentService.java
@Service
public class PaymentService {private int callCount = 0;@Retry(maxAttempts = 5)public void processPayment() {callCount++;if (callCount < 3) {throw new RuntimeException("支付網關超時");}System.out.println("支付成功!");}
}

4. 測試輸出

第 1 次嘗試失敗
第 2 次嘗試失敗
支付成功!

6. 事務管理(Transaction Management)

場景:自動管理數據庫事務(簡化版示例)。

代碼實現

1. 事務管理器偽代碼

// util/TransactionManager.java
@Component
public class TransactionManager {public void begin() {System.out.println("開啟事務");}public void commit() {System.out.println("提交事務");}public void rollback() {System.out.println("回滾事務");}
}

2. 切面邏輯

// aop/TransactionAspect.java
@Aspect
@Component
public class TransactionAspect {@Autowiredprivate TransactionManager txManager;@Around("@annotation(com.example.annotation.Transactional)")public Object manageTransaction(ProceedingJoinPoint pjp) throws Throwable {txManager.begin();try {Object result = pjp.proceed();txManager.commit();return result;} catch (Exception e) {txManager.rollback();throw e;}}
}

3. 業務類使用

// service/OrderService.java
@Service
public class OrderService {@Transactionalpublic void createOrder() {System.out.println("執行訂單創建邏輯...");// 模擬數據庫操作}
}

4. 測試輸出

開啟事務
執行訂單創建邏輯...
提交事務

7. 接口限流(Rate Limiting)

場景:限制接口的調用頻率。

代碼實現

1. 限流注解

// annotation/RateLimit.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {int value() default 5; // 每秒允許的最大請求數
}

2. 切面邏輯

// aop/RateLimitAspect.java
@Aspect
@Component
public class RateLimitAspect {private Map<String, RateLimiter> limiters = new ConcurrentHashMap<>();@Around("@annotation(rateLimit)")public Object limit(ProceedingJoinPoint pjp, RateLimit rateLimit) throws Throwable {String methodName = pjp.getSignature().toShortString();RateLimiter limiter = limiters.computeIfAbsent(methodName, k -> RateLimiter.create(rateLimit.value()));if (limiter.tryAcquire()) {return pjp.proceed();} else {throw new RuntimeException("接口請求過于頻繁");}}
}

3. 業務類使用

// service/ApiService.java
@Service
public class ApiService {@RateLimit(2) // 每秒最多2次調用public String getData() {return "敏感數據";}
}

總結表格

應用場景核心注解通知類型關鍵實現技術
日志記錄@Loggable@AroundSlf4j + 方法元數據獲取
權限校驗@RequireRole@Before權限上下文 + 條件判斷
性能監控無(使用execution)@Around時間計算 + 方法過濾
緩存處理@Cacheable@Around本地緩存(ConcurrentHashMap)
重試機制@Retry@Around循環控制 + 異常捕獲
事務管理@Transactional@Around事務管理器模擬
接口限流@RateLimit@AroundRateLimiter + 方法標識管理

注意事項

  1. 所有切面類必須被 Spring 掃描到(確保包路徑正確)
  2. 同類內部方法調用不會觸發 AOP(需通過代理對象調用)
  3. 性能敏感場景慎用 AOP(會增加方法調用棧深度)

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

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

相關文章

開始一個vue項目-day2

這次新增的功能有&#xff1a; 1、使用cookie存儲token 參考網站:https://vueuse.org/ 安裝包&#xff1a; npm i vueuse/integrations npm i universal-cookie^7 2、cookie的設置讀取和刪除&#xff0c;代碼&#xff1a;composables/auth.js import { useCookies } from …

「Mac暢玩AIGC與多模態18」開發篇14 - 多字段輸出與結構控制工作流示例

一、概述 本篇在輸入變量基礎上,演示如何通過執行 LLM 節點輸出多個結構化字段,并傳遞至結束節點。開發人員將掌握如何配置結構化輸出格式,實現提示詞與字段的準確映射,為后續引入條件判斷、循環結構等邏輯控制建立結構輸出規范基礎。 二、環境準備 macOS 系統Dify 平臺已…

JWT解析

什么是JWT JSON Web Token &#xff08;JWT&#xff09; 是一種開放標準 &#xff08;RFC 7519&#xff09;&#xff0c;它定義了一種緊湊且獨立的方式&#xff0c;用于在各方之間以 JSON 對象的形式安全地傳輸信息。此信息可以驗證和信任&#xff0c;因為它是經過數字簽名的。…

C語言中的自定義類型 —— 結構體.位段.聯合體和枚舉

自定義類型 1. 前言2. 結構體2.1 結構體的聲明2.2 結構體變量的定義和初始化2.3 結構體的特殊聲明2.4 結構體的自引用2.5 結構體的內存對齊2.6 修改默認對齊數2.7 結構體傳參 3. 位段4. 聯合體5. 枚舉6. 結言 1. 前言 在C語言中已經為用過戶提供了內置類型&#xff0c;如&…

StarRocks 查詢優化器深度解析

StarRocks 查詢優化器概覽 1. Development History of StarRocks 過去五年&#xff0c;StarRocks 發布了三個大版本&#xff1a; StarRocks 1.0&#xff1a;通過向量化引擎和 CBO&#xff0c;打造極速 OLAP 數據庫。 StarRocks 2.0&#xff1a;通過主鍵模型、數據湖分析和查詢…

如何提高情商?(優化版)

引言 提高情商&#xff08;EQ&#xff09;是一個需要長期練習和自我反思的過程&#xff0c;核心在于理解自己、管理情緒、共情他人并有效溝通。以下是一些具體且可操作的方法&#xff0c;結合理論和實際場景&#xff0c;幫助你逐步提升&#xff1a; 一、核心方法&#xff1a;…

Python爬蟲實戰:獲取好大夫在線各專業全國醫院排行榜數據并分析,為患者就醫做參考

一、引言 在當今醫療資源豐富但分布不均的背景下,患者在選擇合適的心血管內科醫院時面臨諸多困難。好大夫在線提供的醫院排行榜數據包含了醫院排名、線上服務得分、患者評價得分等重要信息,對患者選擇醫院具有重要的參考價值。本研究通過爬取該排行榜數據,并進行深入分析,…

【AI面試準備】電商購物車AI測試設計與實施

面試題&#xff1a;案例實踐&#xff1a; 為電商購物車設計AI測試&#xff1a;通過用戶行為日志訓練點擊路徑預測模型&#xff0c;動態生成邊界條件測試用例。 為了順利通過面試&#xff0c;回答應結構清晰、技術深入&#xff0c;并突出實際應用與創新。以下為分步解答&#…

Java 中使用 Callable 創建線程的方法

一、Callable 接口概述? Callable接口位于java.util.concurrent包中&#xff0c;與Runnable接口類似&#xff0c;同樣用于定義線程執行的任務&#xff0c;但它具有以下獨特特性&#xff1a;? 支持返回值&#xff1a;Callable接口聲明了一個call()方法&#xff0c;該方法會在…

2025-SMS短信驗證服務或存風險,小心賬號隱私“失守”

近期&#xff0c;火絨安全情報中心監測到一款偽裝成具備SMS短信驗證碼接收服務的程序。該程序通過部署持久化后門&#xff08;即僵尸網絡節點&#xff09;竊取敏感信息。火絨安全提醒廣大用戶務必從官方或可信渠道下載軟件&#xff0c;避免因使用來路不明的程序而導致賬號被盜或…

docker部署Open WebUI下載速度慢解決方法

docker pull ghcr.nju.edu.cn/open-webui/open-webui:main改成這個就可以了

氣泡圖、桑基圖的繪制

1、氣泡圖 使用氣泡圖分析某一年中國同歐洲各國之間的貿易情況。 氣泡圖分析的三個維度&#xff1a; ? 進口額&#xff1a;橫軸 ? 出口額&#xff1a;縱軸 ? 進出口總額&#xff1a;氣泡大小 數據來源&#xff1a;鏈接: 國家統計局數據 數據概覽&#xff08;進出口總額&…

前端面經-VUE3篇(三)--vue Router(二)導航守衛、路由元信息、路由懶加載、動態路由

一、導航守衛 vue Router 中的 導航守衛&#xff08;Navigation Guards&#xff09; 是一個非常重要的功能&#xff0c;用于在路由切換過程中&#xff0c;攔截、控制、檢查或延遲頁面跳轉。 你可以理解為&#xff1a; &#x1f510; “進門前的保安”&#xff0c;控制哪些頁面…

MATLAB實現二氧化硅和硅光纖的單模光波特性與仿真

一.二氧化硅和硅光纖的單模光波特性 利用麥克斯方程的精確解研究二氧化硅和硅亞波長直徑導線的單模光波特性。研究了單模條件、模場。 二氧化硅光纖導線是圓形截面&#xff0c;包層是空氣包層&#xff0c;階梯型變化的折射率&#xff0c;導線線徑D非常小長度足夠長&#xff0…

【Linux系統】第二節—基礎指令(2)

hello ~ 好久不見 自己想要的快樂要自己好好爭取&#xff01; 云邊有個稻草人-個人主頁 Linux—本篇文章所屬專欄—歡迎訂閱—持續更新中 目錄 本節課核心指令知識點總結 本節基本指令詳解 07.man 指令 08.cp 指令 09.mv 指令 10.cat 指令 11.more 指令 12.less 指令 …

為了結合后端而學習前端的學習日志——【黑洞光標特效】

前端設計專欄 今天給大家帶來一個超酷的前端特效——黑洞光標&#xff01;讓你的鼠標變成一個會吞噬光粒子的迷你黑洞&#xff0c;點擊時還會噴射出綠色能量粒子&#xff01;&#x1f320; &#x1f680; 效果預覽 想象一下&#xff1a;你的鼠標變成一個旋轉的黑洞&#xff0…

[硬件電路-11]:模擬電路常見元器件 - 什么是阻抗、什么是輸入阻抗、什么是輸出阻抗?阻抗、輸入阻抗與輸出阻抗的全面解析

1. 阻抗&#xff08;Impedance&#xff09; 定義&#xff1a;阻抗是電路或元件對交流信號&#xff08;AC&#xff09;流動的阻礙能力&#xff0c;用符號Z表示&#xff0c;單位為歐姆&#xff08;Ω&#xff09;。它綜合了電阻&#xff08;R&#xff09;、電感&#xff08;L&am…

機器學習和深度學習的對比

深度 數據經過深層網絡后&#xff0c;語義信息表征能力強&#xff0c;對幾何細節信息表征能力弱。 數據依賴性 深度學習算法需要大量的數據來訓練&#xff0c;而傳統的機器學習使用制定的規則。所以&#xff0c;當數據量少時&#xff0c;深度學習的性能差于機器學習&#xf…

Kubernetes 安裝 minikube

安裝 minikube 在 Ubuntu 上安裝 minikube minikube 是一個工具&#xff0c;它可以在本地快速運行一個單節點的 Kubernetes 集群。它主要用于&#xff1a;本地學習 Kubernetes、測試和開發 Kubernetes 應用程序、快速嘗試 Kubernetes 的功能。 系統配置最低要求如下 CPU&#…

【學習筆記】深度學習:典型應用

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程&#xff0c;深度學習領域研究生必讀教材),開始深度學習領域學習&#xff0c;深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…