SPEL表达式配合自定义注解解析

对缓存的key进行优化:支持SPEL表达式

举例:skuInfo:#{#params[0]}

实现思路:

1、在@GmallCache注解上添加上一个cacheKey属性,让使用者显示来指定缓存的key

2、在AOP切面类中使用解析SPEL表达式,获取具体的key值

SpelExpressionParser

要想对SPEL表达式进行解析,那么此时就需要使用到SpelExpressionParser对象。

官网地址:https://docs.spring.io/spring-framework/docs/5.3.26-SNAPSHOT/reference/html/core.html#expressions

SpelExpressionParser入门

SpelExpressionParser解析表达式的时候支持运算、方法调用、静态方法调用。

@Test
publicvoidsepl01() {
    //SpelExpressionParser入门
    // 在Spel表达式中如果想表示一个字符串需要使用''将字符串引起了,否在就会当做成是一个变量
    Stringstr01="'hello'" ;//字符串
    Stringstr02="1 + 1" ;//可以进行运算
    Stringstr03="'hello'.toUpperCase()" ;//可以表达式方法调用
    Stringstr04="T(java.util.UUID).randomUUID().toString().replace('-' , '')" ;//可以调用静态方法
    SpelExpressionParser spelExpressionParser=newSpelExpressionParser() ;
    Expressionexpression=spelExpressionParser.parseExpression(str04);
    Stringvalue=expression.getValue(String.class);
    System.out.println(value);
}

ParserContext指定解析边界

作为一个表达式而言,有时可能只需要将其一部分通过解析器进行解析。那么此时就需要使用ParserContext定义解析器要解析的边界。

// ParserContext定义解析边界
@Test
publicvoidsepl02() {
    Stringstr="skuInfo:#{1 + 1}:#{'hello'.toUpperCase()}:#{T(java.util.UUID).randomUUID().toString().replace('-' , '')}" ;
    SpelExpressionParser spelExpressionParser=newSpelExpressionParser() ;
    Expressionexpression=spelExpressionParser.parseExpression(str , ParserContext.TEMPLATE_EXPRESSION);//ParserContext.TEMPLATE_EXPRESSION解析格式前缀#{后缀}
    Stringvalue=expression.getValue(String.class);
    System.out.println(value);
}

从SpelExpressionParser上下文对象中动态获取值

上述的表达式还并不算特别灵活【比如hello字符串是直接写死的】,在SPEL表达式中支持从SpelExpressionParser上下文对象中动态获取执行。

使用思想:

1、在SpelExpressionParser上下文对象存储变量的值

2、在表达式中使用#变量名获取表达式的值

@Test
publicvoidsepl03() {
    Stringstr="skuInfo:#{#params.toUpperCase()}" ;
    SpelExpressionParser spelExpressionParser=newSpelExpressionParser() ;
    Expressionexpression=spelExpressionParser.parseExpression(str , ParserContext.TEMPLATE_EXPRESSION);
    EvaluationContext evaluationContext=newStandardEvaluationContext() ;   // SPEL表达式上下文对象
    evaluationContext.setVariable("params" , "hello");
    Stringvalue=expression.getValue(evaluationContext , String.class);     // 获取值的时候将上下文对象作为方法参数传递过去
    System.out.println(value);
}
spel表达式实战
从SpelExpressionParser上下文对象中动态获取值:解析"sku:info:#{#params[0]}"
//params为获取到方法参数数组后 自定义的参数数组的名字
1.(自定义注解添加需要的属性)cacheKey
2.业务方法@GmallCache注解为自定义属性cacheKey赋值
3.创建解析spel表达式的方法

注解添加cacheKey属性**:

@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target(ElementType.METHOD)//生效在方法上
public@interface GMallCache {
​
    public String cacheKey() ;  // 用来让使用者指定缓存的key的名称(即赋值给这个参数)
​
}

业务方法@GmallCache注解添加cacheKey属性:

@GmallCache(cacheKey="sku:info:#{#params[0]}")

解析spel表达式

// SpelExpressionParser是线程安全的
private static final SpelExpressionParser spelExpressionParser=newSpelExpressionParser() ;
​
// 通过解析获取自定义的缓存key
public<T>TparaseExpression(ProceedingJoinPoint proceedingJoinPoint , StringcacheKey , Class<T>  clazz) {
    Expressionexpression=spelExpressionParser.parseExpression(cacheKey, ParserContext.TEMPLATE_EXPRESSION);
    EvaluationContext evaluationContext=newStandardEvaluationContext() ;
    evaluationContext.setVariable("params" , proceedingJoinPoint.getArgs());
    TcacheKeyData=expression.getValue(evaluationContext, clazz);
    returncacheKeyData ;
}

扩展:获取方法的返回值类型

// 获取目标方法的返回值类型
public Type getMethodType(ProceedingJoinPoint proceedingJoinPoint) {
    MethodSignature methodSignature= (MethodSignature) proceedingJoinPoint.getSignature() ;
    Methodmethod=methodSignature.getMethod();
    TypegenericReturnType=method.getGenericReturnType();
    returngenericReturnType ;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值