SpringBootAOP + SpringEL表达式 实现动态传参(基于MethodBasedEvaluationContext)

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”。

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

--土拨鼠--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值