SpringBootAOP + SpringEL表达式 实现动态传参(基于MethodBasedEvaluationContext)
SPEL表达式
Spring 提供的EL表达式解析特性强化了注解能力。能做到注解中的属性值动态地从方法参数中获取,而不是简单地设置固定值。
AOP依赖
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.1.17.RELEASE</version> </dependency>
|
自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface LogAnn { String operator() default "";
String bizNo() default ""; BusinessAction action() default BusinessAction.OTHER; }
|
操作字段的枚举类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public enum BusinessAction {
OTHER,
INSERT,
UPDATE,
DELETE,
GRANT,
EXPORT,
IMPORT,
FORCE,
GENCODE,
CLEAN, }
|
注解的使用方式
其中LogTestModel用于测试,类中包含userName和orderId字段。
1 2 3 4 5 6
| @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解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| @Slf4j @Aspect @Component public class LogAspect {
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
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); 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”。