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

Springboot自定义注解,支持SPEL表达式举例,自定义redis模糊删除注解1.自定义注解importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Target(E…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

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

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

1.自定义注解

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拦截方法,解析注解参数

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

    /**
     * 获取缓存的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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • kali-linux中安装Nessus详细教程「建议收藏」

    kali-linux中安装Nessus详细教程「建议收藏」一、下载NessusNessus是工业界使用较为广泛的产品。登录官网,下载对应版本的nessus框架安装包https://www.tenable.com/downloads/nessus?loginAttempted=true(建议直接在kali中利用firefox浏览器下载,否则需要从真实机拖进虚拟机中(需要安装VMtools,安装VMtools过程不再赘述))二、明确自己压缩包的位置比如我的Nessus-8.10.0-debian6_amd64.deb安装包位于/home/go.

    2022年10月19日
  • PyCharm 占用过大 C 盘空间,system 配置文件迁移

    PyCharm 占用过大 C 盘空间,system 配置文件迁移

    2021年11月22日
  • WMI远程访问问题解决方法

    WMI远程访问问题解决方法

  • redis6.0 源码学习(五)ziplist

    redis6.0源码学习(五)ziplist文章目录redis6.0源码学习(五)ziplist一、数据结构二、代码解析1、创建2、查找3、插入三、总结一、数据结构ziplist是经过特殊编码的双向链接列表,该列表具有很高的内存效率。它存储字符串和整数值,其中整数被编码为实际整数,而不是一系列个字符。它允许对列表的两侧进行push和pop操作且复杂度为O(1)。但是由于每个操作都需要重新分配ziplist使用的内存,实际复杂度与ziplist使用的内存量有关。下图是ziplist得示意图:

  • Nginx(一):Nginx原理概述 与 安装步骤详解

    Nginx(一):Nginx原理概述 与 安装步骤详解

  • stn算子_STN 口袋指南

    stn算子_STN 口袋指南欢迎使用STN®!本页主要介绍STN指令式检索的基本功能。按您可能遇到问题的先后顺序(从登录STN到退出)排列信息。目录登录STN按照以下说明登录STN。界面登录方式STNExpress安装并启动软件。STN安装向导自动启动。有关连接的其他信息,请访问STNExpressSupport。STNext访问STNext。输入您的STN登录ID和密码。进入数据库在箭头提…

    2022年10月19日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号