spring Spel 在aop中的应用

本文介绍了一种使用Spring Expression Language (SPEL)在Aspect Oriented Programming (AOP)中获取方法参数的方法。通过定义特定注解并在业务逻辑中使用,可以灵活地通过SPEL表达式获取所需的参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中时常用到aop切面做一些功能,但是获取切面中方法的参数有多样的方法,我列出我在项目中运用spel的方式:
  • 定义注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RecordAnnotation {
    InterfaceTypeEnum[] interfaceType() default {};
    String desc() default "无描述信息";

    String key() default "";
}

注解就不详细解释了

  • 业务层使用:

/**
     * 获取用户支付宝accessToken信息
     *
     * @return
     */
    @RecordAnnotation(interfaceType = InterfaceTypeEnum.ACCESS_TOKEN ,desc = "getUserAccessToken接口",key = "#req")
    public AlipaySystemOauthTokenResponse getUserAccessToken(ExternalRequest req) {
        String code = req.getOutNo();
        try {
            if (StringUtils.isBlank(code)) {
                log.info("用户授权码为NULL换取授权访问令牌失败");
                return null;
            }
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setGrantType(GRANT_TYPE);
            request.setCode(code);
            return alipayClient.execute(request);
        } catch (AlipayApiException e) {
            log.error("获取AliUserAccessToken异常.", e);
        }
        return null;
    }

注意此处的 #req 一会在下面的切面中会用到

  • 切面中的应用:

@Around("@annotation(ra)")
    public Object process(ProceedingJoinPoint joinPoint, RecordAnnotation ra) throws Throwable {
        //获取当前切面方法的形参
        //new LocalVariableTableParameterNameDiscoverer().getParameterNames(method) spring提供的获取方法中形参的函数
        String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod());
        Object[] args = joinPoint.getArgs();
        Object object = getRequest(ra.key(), parameterNames, args);
        Object obj = null;
        if (object instanceof ExternalRequest) {
            //获取方法参数对象
            ExternalRequest request = (ExternalRequest) object;
            //获取日志对象
            Logger testLog = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
            //TODO something

        }
        return obj;
    }

    /**
     * 通过spring Spel 获取参数
     * @param key               定义的key值 以#开头 例如:#user
     * @param parameterNames    形参
     * @param values             形参值
     * @return
     */
    public Object getRequest(String key, String[] parameterNames, Object[] values) {

        //spel解析器
        ExpressionParser parser = new SpelExpressionParser();
        //spel上下文陪你
        EvaluationContext context = new StandardEvaluationContext();
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], values[i]);
        }
        return parser.parseExpression(key).getValue(context);
    }

此处的 ra.key() 就是上面说到的 #req

  • 输出信息:

15:51:28.179 [main] INFO  c.p.b.e.a.l.AlipayAppService - -result:{"outNo":"10fcedba95a74eb69c0a793e4607YD49"} 

以上就是对我碰到的问题的解决方案,大家有什么意见欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值