美文网首页
基于注解与AOP实现数据库与Redis取值

基于注解与AOP实现数据库与Redis取值

作者: _MrWhite | 来源:发表于2021-02-04 22:24 被阅读0次

    我们经常遇到一种场景, 就是查询数据, 首先去Redis中获取, 如果有数据就返回,
    如果没有就去数据库中进行查询,然后将它放入到数据当中,这样的代码与业务没有太大关系, 可以抽离出来,
    您可能会说Spring的@Cache注解可以实现啊, 但是它的实现不灵活, 有时候还是要自己定义一些东西的.

    import com.alibaba.fastjson.JSON;
    import com.zhangmen.aioneservice.core.utils.RedisUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Random;
    
    /**
     * 获取数据代理类
     *
     * @author: baifan
     * @date: 2021/2/1
     */
    @Slf4j
    @Component
    @Aspect
    public class DBGetProxy {
    
        @Autowired
        RedisUtil redisUtil;
    
        @Pointcut("@annotation(com.zhangmen.aioneservice.core.aop.DBToRedisAop)")
        public void pointCut() {
        }
    
        @Around("pointCut()")
        public Object beforeGetDataFromDB(ProceedingJoinPoint joinPoint) throws Throwable {
            // 获取方法名
            String methodName = joinPoint.getSignature().getName();
            // 反射获取目标类
            Class<?> targetClass = joinPoint.getTarget().getClass();
            // 拿到方法对应的参数类型
            Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
            // 根据类、方法、参数类型(重载)获取到方法的具体信息
            Method objMethod = targetClass.getMethod(methodName, parameterTypes);
            // 拿到方法定义的注解信息
            DBToRedisAop dbToRedisAop = objMethod.getDeclaredAnnotation(DBToRedisAop.class);
    
            String content = dbToRedisAop.content();
            String rawKey = dbToRedisAop.rawKey();
            Object[] args = joinPoint.getArgs();
    
            String key = genKey(rawKey, args);
            log.info("获取{}开始...,key为 {}", content, key);
            Object result = redisUtil.get(key);
            if (result != null) {
                log.info("从缓存中获取到{}:{}", content, result.toString());
                // 得到被代理方法的返回值类型
                //Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
            } else {
                result = joinPoint.proceed(args);
                redisUtil.set(key, result, randomTime(3600));
            }
            return result;
        }
    
        private long randomTime(long time) {
            Random random = new Random();
            return Long.valueOf(random.nextInt(30)) + time;
        }
    
        private String genKey(String rawKey, Object[] args) {
            for (Object arg : args) {
                if (rawKey.contains("{}")) {
                    rawKey = rawKey.replaceFirst("\\{\\}", String.valueOf(arg));
                }
            }
            return rawKey;
        }
    }
    ``
    

    相关文章

      网友评论

          本文标题:基于注解与AOP实现数据库与Redis取值

          本文链接:https://www.haomeiwen.com/subject/ztmitltx.html