• 自定义注解实现Redis缓存


    使用redis做缓存,很多情况下写的都是一样的模板代码,且代码侵入大,于是封装成注解,后面需要缓存的时候只需要加上注解就可以了,话不多说,都在代码里

    注解定义:

    CacheData

    import java.lang.annotation.*;
    
    /**
     * 注解 CacheData 用于简便处理需要进行缓存的操作
     * 注意 增加了全局缓存开关,参数为 global_cache_open_status_key,
     * 若是要关闭所有使用这个注解的缓存,可在nacos 配置中心或者其他配置文件配置 global_cache_open_status_key: false 即可关闭
     * 若是要关闭单个使用注解缓存的地方,在nacos 配置中心或者其他配置文件的地方 配置对应 prefix值: false 即可
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface CacheData {
    
        /**
         * 前缀
         * @return
         */
        String prefix();
    
        /**
         * 后缀表达式,为空时候表示不需要后缀表达式,采用 SPEL
         * eg:
         *  1.不支持加固定后缀!!! 目前spEl数据源是来自方法入参,要是需要固定后缀,放置在前缀就好了;
         *  2.访问参数 比如 methodName(String userId, String pageId)  ->"#userId+'_'+#pageId";
         *  3.访问对象内属性 比如 methodName(UserBO userBO)  ->"#userBO.name";
         *  4.访问集合数据 比如 methodName(List<String> list) -> "#list.toString()";
         *
         * @return
         */
        String suffixExpression() default "";
    
        /**
         * 缓存时间 秒
         * @return
         */
        long expireSecond() default 300;
    
    
    }

    切面类:

    import cn.hutool.core.util.StrUtil;
    import com.alibaba.fastjson.JSON;
    import com.sd.outbound.common.annotation.CacheData;
    import com.sd.outbound.core.CoreConstants;
    import com.soudian.common.StringHelper;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
    import org.springframework.core.env.Environment;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.expression.EvaluationContext;
    import org.springframework.expression.Expression;
    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.lang.reflect.Type;
    
    
    @Slf4j
    @Aspect
    @Component
    public class CacheDataAspect {
    
        private ExpressionParser parser = new SpelExpressionParser();
    
        private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
    
    
        @Autowired
        StringRedisTemplate stringRedisTemplate;
    
        @Autowired
        private Environment env;
    
        @Around("@annotation(cacheData)")
        public Object cacheDataAround(ProceedingJoinPoint pjp, CacheData cacheData) throws Throwable {
            String key = cacheData.prefix();
    
            String currentCacheOpenStatus = env.getProperty(key);
            String globalCacheStatus = env.getProperty(CoreConstants.GLOBAL_CACHE_OPEN_STATUS_KEY);
            log.info("cacheOpenStatus of {} = {}, globalCacheStatus={}", key, currentCacheOpenStatus, globalCacheStatus);
            if(Boolean.FALSE.toString().toLowerCase().equals(globalCacheStatus) || Boolean.FALSE.toString().toLowerCase().equals(currentCacheOpenStatus)){
                return pjp.proceed();
            }
    
            long expireSecond = cacheData.expireSecond();
            Method method = getMethod(pjp);
            Type genericReturnType = method.getGenericReturnType();
    
            if(StringHelper.isNotEmpty(cacheData.suffixExpression())){
                key = StrUtil.join(StrUtil.COLON, key,  parseSpel(getMethod(pjp), pjp.getArgs(), cacheData.suffixExpression()));
            }
            String data = stringRedisTemplate.opsForValue().get(key);
    
            Object result = null;
            if(StringHelper.isNotEmpty(data)){
                result = JSON.parseObject(data, genericReturnType);
                log.info("CacheData get data from cache in method: {}", method.getName());
            }else {
                result = pjp.proceed();
                stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(result), expireSecond);
                log.info("CacheData get data from db in method:{}", method.getName());
            }
    
            return result;
        }
    
        private Object parseSpel(Method method, Object[] arguments, String spel) {
            String[] params = discoverer.getParameterNames(method);
            EvaluationContext context = new StandardEvaluationContext();
            for (int len = 0; len < params.length; len++) {
                context.setVariable(params[len], arguments[len]);
            }
            try {
                Expression expression = parser.parseExpression(spel);
                return expression.getValue(context);
            } catch (Exception e) {
                return StrUtil.EMPTY;
            }
        }
    
        private static Method getMethod(ProceedingJoinPoint pjp) {
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            if (method.getDeclaringClass().isInterface()) {
                try {
                    method = pjp
                            .getTarget()
                            .getClass()
                            .getDeclaredMethod(pjp.getSignature().getName(),
                                    method.getParameterTypes());
                } catch (SecurityException | NoSuchMethodException e) {
                    throw new RuntimeException(e);
                }
            }
    
            return method;
        }
    }

    使用:

        @CacheData(prefix = "user_authority", suffixExpression = "#userId+'_'+#pageId")
        public List<String> getUserIdDataAuthority(String userId,Long pageId){
           ...业务代码... 
    }

    OK.

  • 相关阅读:
    NOI2015 小园丁和老司机
    退役记
    留言板
    $mathfrak {reputation}$
    计算几何基础
    HNOI2018简要题解
    JXOI2018简要题解
    BJOI2018简要题解
    HAOI2018 简要题解
    CQOI2018简要题解
  • 原文地址:https://www.cnblogs.com/heisehenbai/p/15624971.html
Copyright © 2020-2023  润新知