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
微信掃一掃
支付寶掃一掃