SpringBootAOP + SpringEL表达式 实现动态传参(基于MethodBasedEvaluationContext)
SPEL表达式
Spring 提供的EL表达式解析特性强化了注解能力。能做到注解中的属性值动态地从方法参数中获取,而不是简单地设置固定值。
AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.17.RELEASE</version>
</dependency>
自定义注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface LogAnn {
// 操作人
String operator() default "";
// 业务单号
String bizNo() default "";
// 操作
BusinessAction action() default BusinessAction.OTHER;
}
操作字段的枚举类型
public enum BusinessAction {
/**
* 其它
*/
OTHER,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
/**
* 导入
*/
IMPORT,
/**
* 强退
*/
FORCE,
/**
* 生成代码
*/
GENCODE,
/**
* 清空数据
*/
CLEAN,
}
注解的使用方式
其中LogTestModel用于测试,类中包含userName和orderId字段。
@PostMapping("LogAnn")
@LogAnn(operator = "#logTestModel.userName", bizNo = "#logTestModel.orderId", action = BusinessAction.OTHER)
public String LogAnn(@RequestBody LogTestModel logTestModel) {
System.out.println("测试");
return "success";
}
Aspect代码
拦截LogAnn
注解作为切点
使用MethodBasedEvaluationContext
进行SPEL解析
@Slf4j
@Aspect
@Component
public class LogAspect {
/**
* 用于获取方法参数定义名字.
*/
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/**
* 用于SpEL表达式解析.
*/
private static final SpelExpressionParser parser = new SpelExpressionParser();
@Pointcut("@annotation(com.hong.demo.common.annotate3.LogAnn)")
public void LogAnn() {
}
@Around("LogAnn()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取目标类
Object target = joinPoint.getThis();
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
// 获取方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
// 获取参数
Object[] args = joinPoint.getArgs();
// 可解决代理对象问题
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
LogAnn logAnn = method.getAnnotation(LogAnn.class);
MethodBasedEvaluationContext context = new MethodBasedEvaluationContext(target, targetMethod, args, parameterNameDiscoverer);
// 处理注解上的值
String bizNo = logAnn.bizNo();
String bizNoValue = getExpValue(context, bizNo);
log.info("bizNo:{}", bizNoValue);
String operator = logAnn.operator();
String operatorValue = getExpValue(context, operator);
log.info("operator:{}", operatorValue);
// to do
return joinPoint.proceed();
}
private String getExpValue(MethodBasedEvaluationContext context, String expr) {
Expression expression = this.parser.parseExpression(expr);
return (String) expression.getValue(context);
}
}
测试结果
以上就是在AOP中使用SPEL进行动态参数的demo,最后不要忘记在配置中打开“@EnableAspectJAutoProxy”。