Spring框架中的AOP技術(面向切面編程)是一種可以在不修改源代碼的情況下,對系統進行橫向切割的技術。其中,afterreturning是其中一個重要的切面類型,它允許在方法正常返回之後,在方法返回上下文中引入一個切面。下面從多個角度深入理解afterreturning中的細節和用法。
一、用法概述
正如其名,afterreturning是在方法正常返回之後執行的增強類型。它擁有三個最常用的屬性:
- value:指定切點表達式
- returning:指定一個用於接受方法返回值的參數名
- argNames:指定方法參數名,逗號分隔
下面是一個afterreturning的示例:
@Aspect @Component public class LogAspect { @AfterReturning(value = "execution(* com.example.service.UserService.*(..))", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); String className = joinPoint.getTarget().getClass().getSimpleName(); System.out.println("AfterReturning: " + className + " " + methodName + " returning " + result); } }
以上代碼實現了在UserService中方法正常返回之後輸出方法名稱和返回結果的功能。這裡需要注意的是,returning屬性指定的參數名稱必須要與方法簽名中的參數名完全一致,否則無法正常接收返回值。
二、如何獲取方法參數
有時候我們需要獲取方法的各個參數來進一步處理,對於這個需求,afterreturning也可以支持。需要藉助兩個註解:@AfterReturning和@AfterReturning arg。示例代碼如下:
@AfterReturning(value = "execution(* com.example.service.UserService.*(..))", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); String className = joinPoint.getTarget().getClass().getSimpleName(); System.out.println("AfterReturning: " + className + " " + methodName + " returning " + result); Object[] args = joinPoint.getArgs(); for (Object obj : args) { if (obj instanceof HttpServletRequest) { System.out.println("HttpServletRequest: " + obj); } } } @AfterReturning(argNames = "request,result", value = "execution(* com.example.controller.UserController.getAll(..))") public void logAfterReturning(JoinPoint joinPoint, HttpServletRequest request, Object result) { String methodName = joinPoint.getSignature().getName(); String className = joinPoint.getTarget().getClass().getSimpleName(); System.out.println("AfterReturning: " + className + " " + methodName + " returning " + result); }
以上代碼演示了如何獲取方法中的HttpServletRequest參數。需要注意的是,在後面的示例代碼中,argNames屬性指定了方法簽名中的參數名,這樣我們就能夠通過參數名將參數一一對應起來,方便我們在增強中處理它們。
三、afterreturning的用途
在實際應用中,afterreturning有很多種用途。下面我們列出了三種最常見的:
1、日誌輸出
以前面的日誌輸出示例為例,afterreturning是用來實現日誌輸出功能的。在方法正常返回之後,通過增強完成打印日誌的功能。
2、返回值處理
有時候,我們需要對方法返回值進行一些處理。例如,添加一些統一的前綴或後綴等等。下面是一個示例代碼:
@AfterReturning(value = "execution(* com.example.service.UserService.*(..))", returning = "result") public void addPrefixToResult(JoinPoint joinPoint, Object result) { String className = joinPoint.getTarget().getClass().getSimpleName(); if (result instanceof String) { result = "[Prefix]" + result + "[Suffix]"; } System.out.println("AfterReturning: " + className + " returning " + result); }
以上代碼實現了給返回的String類型結果添加Prefix和Suffix的功能。需要注意的是,result是一個Object類型,需要判斷其是否為String類型,然後再進行增強操作。
3、緩存實現
通過緩存實現數據的快速讀取是很多高並發場景下的解決方案。在Spring中,afterreturning可以用於緩存實現,示例代碼如下:
@AfterReturning(value = "execution(* com.example.service.UserService.getUserById(String)) && args(id)", returning = "result") public void cacheUserById(String id, UserDTO userDTO) { redisTemplate.opsForValue().set(id, userDTO); }
以上代碼實現了通過ID緩存UserDTO的功能,在方法正常返回之後將其緩存到Redis中,下次查詢相同的ID時可以避免數據庫查詢的開銷。
四、總結
本文從用法概述、如何獲取方法參數、afterreturning的用途三個方面深入理解了afterreturning的細節和用法。通過靈活使用這個切面類型,我們可以避免在修改源代碼的情況下進行代碼橫向切割和重構。
原創文章,作者:GULJI,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/370212.html