项目中有使用到缓存,每次需要将缓存代码和业务代码杂糅在一起,以及分散各处的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、应用案例:

基于Redis的Service缓存实现的更多相关文章

  1. 基于redis的分布式缓存disgear开源到github上了

    disgear是笔者参考solrcloud架构基于redis实现的分布式的缓存,支持数据切分到多台机器上,支持HA,支持读写分离和主节点失效自动选举,目前把它开放到github上,开放给大家 gith ...

  2. Govern Service 基于 Redis 的服务治理平台

    Govern Service 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心) Govern Service 是一个轻量级.低成本的服务注册.服务发现. 配置服务 SDK,通过 ...

  3. 基于Spring接口,集成Caffeine+Redis两级缓存

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 在上一篇文章Redis+Caffeine两级缓存,让访问速度纵享丝滑中,我们介绍了3种整合Caffeine和Redis作为两级缓存使用的方法,虽 ...

  4. 基于redis分布式缓存实现(新浪微博案例)

    第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的API. 第二:出现背景 数据结构(Data Structure)需求越来 ...

  5. .NET基于Redis缓存实现单点登录SSO的解决方案[转]

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  6. .NET基于Redis缓存实现单点登录SSO的解决方案

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  7. 基于redis分布式缓存实现

    Redis的复制功能是完全建立在之前我们讨论过的基 于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你 的 ...

  8. 基于Redis缓存的Session共享(附源码)

    基于Redis缓存的Session共享(附源码) 在上一篇文章中我们研究了Redis的安装及一些基本的缓存操作,今天我们就利用Redis缓存实现一个Session共享,基于.NET平台的Seesion ...

  9. redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现

    本次分享如何使用redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现思路    现在的互联网公司大多数都是以Redis作为缓存,使用缓存的优点就不赘述了,写这篇文章的目的就是想帮助同学们如 ...

随机推荐

  1. 一天一个设计模式——Builder建造者模式

    一.模式说明 在现实世界中,当我们要构造一个大型工程时(建一个大楼),通常的做法是先建造工程的每个独立部分,然后再逐步构造完成(先打地基,再搭框架,最后逐层累造).在程序设计领域,构造一个复杂的类时( ...

  2. 9.1hadoop 内置计数器、自定义枚举计数器、Streaming计数器

    1.1  计数器 计数器的作用是用来统计数量的,用于记录特定事件的次数,分为内置计数器.自定义java枚举计数器.自定义Stream计数器三大类.用于质量分析,或应用级统计.分析计数器的值比分析一堆日 ...

  3. npm全局权限设置 - Mac

    网络上的常见方法 目前网络上常见的方法都是修改npm安装路径的权限 通过使用命令 npm config get prefix 得到npm的路径,结果大部分都是/usr/local.然后,很多方法都会要 ...

  4. ci框架与smarty的整合

    ci框架与smarty的整合 来源:未知    时间:2014-10-20 11:38   阅读数:108   作者:xbdadmin [导读] Ci 和 smarty 的完美结合 Ci 结合 sma ...

  5. 吴裕雄--天生自然 JAVASCRIPT开发学习:Window - 浏览器对象模型

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 从Evernote大批顶尖高管离职,看处于漩涡中的笔记应用未来前景

    无论是巨头,还是独角兽,甚至是小而美的某些企业,在发生高管离职.裁员等情况时,总会引起业界的广泛关注.究其原因,就在于高管离职.裁员等往往意味着企业内部发生了动荡,甚至还会直接反映出所在行业的发展趋势 ...

  7. Linux(CENTOS7) RabbitMq安装

    RabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...

  8. 91.一次性处理多条数据的方法:bulk_create,update,delete

    (1)bulk_create: 可以一次性的创建多个对象 示例代码如下: from django.http import HttpResponse from .models import Pulish ...

  9. JDK11 JAVA11下载安装与快速配置环境变量教程

    https://blog.csdn.net/weixin_40928253/article/details/83590136 1.到Oracle官网下载jdk11,并安装.搜索“jdk",选 ...

  10. JavaScript sort()方法总结

    sort() 方法用于对数组的元素进行排序. 语法:arrayObject.sort(sortby):参数sortby可选.规定排序顺序.必须是函数. 注:如果调用该方法时没有使用参数,将按字母顺序对 ...