前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Springboot自定义注解,支持SPEL表达式

Springboot自定义注解,支持SPEL表达式

作者头像
全栈程序员站长
发布2022-11-15 18:10:12
7060
发布2022-11-15 18:10:12
举报
文章被收录于专栏:全栈程序员必看

举例,自定义redis模糊删除注解

1.自定义注解

代码语言:javascript
复制
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheEvictFuzzy {
    /**
     * redis key集合,模糊删除
     * @return
     */
    String[] key() default "";

}

Jetbrains全家桶1年46,售后保障稳定

2.使用AOP拦截方法,解析注解参数

代码语言:javascript
复制
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Set;
@Aspect
@Order(1)
@Component
public class CacheCleanFuzzyAspect {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RedisUtil redis;
//指定要执行AOP的方法
@Pointcut(value = "@annotation(cacheEvictFuzzy)")
public void pointCut(CacheEvictFuzzy cacheEvictFuzzy){}
// 设置切面为加有 @RedisCacheable注解的方法
@Around("@annotation(cacheEvictFuzzy)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, CacheEvictFuzzy cacheEvictFuzzy){
return doRedis(proceedingJoinPoint, cacheEvictFuzzy);
}
@AfterThrowing(pointcut = "@annotation(cacheEvictFuzzy)", throwing = "error")
public void afterThrowing (Throwable  error, CacheEvictFuzzy cacheEvictFuzzy){
logger.error(error.getMessage());
}
/**
* 删除缓存
* @param proceedingJoinPoint
* @param cacheEvictFuzzy
* @return
*/
private Object doRedis (ProceedingJoinPoint proceedingJoinPoint, CacheEvictFuzzy cacheEvictFuzzy){
Object result = null;
//得到被切面修饰的方法的参数列表
Object[] args = proceedingJoinPoint.getArgs();
// 得到被代理的方法
Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
String[] keys = cacheEvictFuzzy.key();
Set<String> keySet = null;
String realkey = "";
for (int i = 0; i < keys.length; i++) {
if (StringUtils.isBlank(keys[i])){
continue;
}
realkey = parseKey(keys[i], method, args);
keySet = redis.keys("*"+realkey+"*");
if (null != keySet && keySet.size()>0){
redis.delKeys(keySet);
logger.debug("拦截到方法:" + proceedingJoinPoint.getSignature().getName() + "方法");
logger.debug("删除的数据key为:"+keySet.toString());
}
}
try {
result = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}finally {
return result;
}
}
/**
* 获取缓存的key
* key 定义在注解上,支持SPEL表达式
* @return
*/
private String parseKey(String key, Method method, Object [] args){
if(StringUtils.isEmpty(key)) return null;
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for(int i=0;i<paraNameArr.length;i++){
context.setVariable(paraNameArr[i], args[i]);
}
return parser.parseExpression(key).getValue(context,String.class);
}
}

完事啦!

大家可以注意到关键方法就是parseKey

代码语言:javascript
复制
    /**
* 获取缓存的key
* key 定义在注解上,支持SPEL表达式
* @return
*/
private String parseKey(String key, Method method, Object [] args){
if(StringUtils.isEmpty(key)) return null;
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for(int i=0;i<paraNameArr.length;i++){
context.setVariable(paraNameArr[i], args[i]);
}
return parser.parseExpression(key).getValue(context,String.class);
}

ok啦,大家记得点赞加关注啊!

双击评论666走起!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/230826.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档