基于Redis的Service缓存实现

项目中有使用到缓存,每次需要将缓存代码和业务代码杂糅在一起,以及分散各处的key,严重影响代码的可读性。以下是使用AOP对其简单尝试。直接上代码:

1、定义缓存注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {
    long timeOut() default 0;

    TimeUnit timeUnit() default TimeUnit.HOURS;
}

 

2、定义参数唯一键注解,使用此注解标记此输入参数参与构成唯一键:

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheUniqueKey {
}

 

3、CacheAspect

@Component
@Slf4j
@Aspect
@Data
public class CacheAspect {
    private final CacheCenter<String> cacheCenter;
   // 缓存开关配置
    @Value("${service.cache}")
    private boolean cacheEnable = false;

    @Around(value = "@annotation(com.yingying.survey.component.cache.Cache)&&@annotation(cache)")
    public Object around(ProceedingJoinPoint joinPoint, Cache cache) throws Throwable {
        if (!cacheEnable) {
            return joinPoint.proceed();
        }

        long timeOut = cache.timeOut();
        TimeUnit timeUnit = cache.timeUnit();
        if (timeOut == 0) {
            return joinPoint.proceed();
        }

        Class<?> clazz = joinPoint.getTarget().getClass();
        String clazzSimpleName = clazz.getSimpleName();
        String methodName = joinPoint.getSignature().getName();

        Signature signature = joinPoint.getSignature();
        Class declaringType = ((MethodSignature) signature).getReturnType();

        String uniqueParam = methodParamsResolve(joinPoint);
        String cacheKey = clazzSimpleName + ":" + methodName + ":" + uniqueParam;
        if (cacheCenter.isExistCache(cacheKey)) {
            String loadCache = cacheCenter.loadCache(cacheKey);
            log.info("data from cache:{}", loadCache);
            if (declaringType.isArray()) {
                return JSONArray.parseArray(loadCache, declaringType);
            } else {
                return JSON.parse(loadCache, declaringType);
            }
        }

        Object proceedResult = joinPoint.proceed();
        // 为了从缓存中取值时不出现空指针的情况,现不对返回值为空的结果缓存。
        if (proceedResult != null) {
            String cacheData = JSON.json(proceedResult);
            CacheUnit cacheUnit = new CacheUnit().setTimeUnit(timeUnit).setCacheOutTime(timeOut).setCacheKey(cacheKey);
            cacheCenter.insertCache(cacheUnit, cacheData);
        }

        return proceedResult;
    }

    private String methodParamsResolve(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        Method method = ((MethodSignature) signature).getMethod();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();

        String uniqueParam = "";
        int idx = 0;
        for (Annotation[] annotations : parameterAnnotations) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof CacheUniqueKey) {
                    Object[] args = joinPoint.getArgs();
                    uniqueParam = (String) args[idx];
                    return uniqueParam;
                }
            }
            idx++;
        }
        return uniqueParam;
    }
}

 

4、缓存配置单元:

@Data
@Accessors(chain = true)
public class CacheUnit {
    @NotBlank
    @NotNull
    private String cacheKey;

    private long cacheOutTime = 0;

    @NotNull
    private TimeUnit timeUnit;
}

 

5、缓存中心实现接口:

public interface CacheCenter<T> {
    boolean isExistCache(@NotNull @NotBlank String cacheKey);

    T loadCache(@NotNull @NotBlank String cacheKey);

    boolean insertCache(@NotNull CacheUnit cacheUnit, @NotNull T cacheData);
}

 

6、基于Redis的缓存中心实现:

@Service("cacheCenter")
@Data
public class RedisCacheCenter implements CacheCenter<String> {
    private final RedisService redisService;

    @Override
    public boolean isExistCache(@NotNull @NotBlank String cacheKey) {
        return redisService.exists(cacheKey);
    }

    @Override
    public String loadCache(@NotNull @NotBlank String cacheKey) {
        return redisService.get(cacheKey);
    }

    @Override
    public boolean insertCache(@NotNull CacheUnit cacheUnit, @NotNull String cacheData) {
        long cacheOutTime = TimeUnit.SECONDS.convert(cacheUnit.getCacheOutTime(), cacheUnit.getTimeUnit());
        redisService.set(cacheUnit.getCacheKey().getBytes(), cacheData.getBytes(), cacheOutTime);
        return true;
    }
}

 

7、应用案例:

 

转载于:https://www.cnblogs.com/watson-ljf/p/10336995.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值