在使用Spring AOP做切面时,对方法增强处理,经常需要获取方法参数。需要使用JoinPoint作为第一个参数,因为当该代理方法执行时,JoinPoint代表了织入增强处理的连接点。JoinPoint通常使用的有四个方法
Object[] getArgs:获取目标方法的参数数组
Signature getSignature:获取目标方法的签名
Object getTarget:获取被织入增强处理的目标对象
Object getThis:获取AOP框架为目标对象生成的代理对象
如果每一个代理方法都要写一些获取参数的方法,代码非常冗余,不简洁,重复代码很多。写了一个工具类,可以通过这个工具类直接获取到织入连接点(JoinPoint)中的被代理方法参数。
package com.lsz.common.spring;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;/**
* JoinPoint 工具类
*
* @author lishuzhen
* @date 2020/10/10 18:27
*/
public class JoinPointUtils {/**
* 从 joinPoint 中 根据 参数名称 获取参数
*
* @param joinPoint
* @param paramName
* @return
* @author Lishuzhen
*/
public static <T> T getParamByName(JoinPoint joinPoint, String paramName, Class<T> clazz) {
// 获取所有参数的值
Object[] args = joinPoint.getArgs();
// 获取方法签名
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
// 在方法签名中获取所有参数的名称
String[] parameterNames = methodSignature.getParameterNames();
// 根据参数名称拿到下标, 参数值的数组和参数名称的数组下标是一一对应的
int index = ArrayUtils.indexOf(parameterNames, paramName);
// 在参数数组中取出下标对应参数值
Object obj = args[index];if (obj == null) {
return null;
}// 将object对象转为Class返回
if (clazz.isInstance(obj)) {
return clazz.cast(obj);
}return (T) obj;
}}
工具类在切面中使用
package com.lsz.consumer.aop;
import com.lsz.common.spring.JoinPointUtils;
import com.lsz.consumer.dto.ConsumerUserInfoDTO;
import com.lsz.consumer.jjwt.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/**
* 用户二维码切面
*
* @author lishuzhen
* @date 2020/10/10 18:19
*/
@Slf4j
@Aspect
@Component
public class UserQRCodeAspect {@Autowired
RedisUtils redisUtils;/**
* 将二维码设置为无效 切点
*/
@Pointcut(“execution(public * com.lsz.consumer.service.api.UserQRCodeServiceApi.getUserInfoByQRCode(..))”)
public void setInvalidPointCut() {
}/**
* 将二维码设置为无效
*
* @param joinPoint
* @param consumerUserInfo
* @return
*/
@AfterReturning(value = “setInvalidPointCut()”, returning = “consumerUserInfo”)
public Object qrCodeSetInvalid(JoinPoint joinPoint, ConsumerUserInfoDTO consumerUserInfo) {
String code = JoinPointUtils.getParamByName(joinPoint, “code”, String.class);
redisUtils.remove(code);
return consumerUserInfo;
}}