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

2021-02-04  本文已影响0人  _MrWhite

我们经常遇到一种场景, 就是查询数据, 首先去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;
    }
}
``
上一篇 下一篇

猜你喜欢

热点阅读