项目中有使用到缓存,每次需要将缓存代码和业务代码杂糅在一起,以及分散各处的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. POJ 2006:Litmus Test 化学公式

    Litmus Test Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1709   Accepted: 897 Descri ...

  2. 题解P4201: [NOI2008]设计路线

    发现给出了一棵树, 不是树的情况直接输出-1 考虑进行DP, 设f[i][0/1/2]为i的子树中选小于等于0/1/2条边修路的方案数, 不妨对于一个节点, 先考虑正好相等的情况, 假设当前扫到了一个 ...

  3. xlua 原理

    基于版本 104 可以直接在lua访问c#函数原理: CS 是一个table,设置了一个__index函数,如果访问不存在的成员的时候,会走__index函数,调用import_type从C#中找到具 ...

  4. mysql float 这个大坑

    以后高精度的数据不要用这个字段  今天同事反应 应该是17390.7的数据 结果展示17390.6992  找了半天问题在哪 后来决定先不管  手动现在数据库改数据 结果手动改也改不过来  于是能确定 ...

  5. 墙壁涂色(DP)

    蒜头君觉得白色的墙面好单调,他决定给房间的墙面涂上颜色. 他买了 3 种颜料分别是红.黄.蓝,然后把房间的墙壁竖直地划分成 n 个部分,蒜头希望每个相邻的部分颜色不能相同. 他想知道一共有多少种给房间 ...

  6. MySQL--mysql中You can’t specify target table for update in FROM clause错误解决方法

    参考:http://www.jb51.net/article/60926.htm mysql中You can't specify target table for update in FROM cla ...

  7. sudo: /etc/sudoers is mode 0777, should be 0440 单用户 sudo不用输入密码的方法

    sudo权限问题考察一题  su -   sudo su -    sudo su - test [root@localhost ~]# su - zzx   #root用户进行切换不需要输入密码 [ ...

  8. Cracking Digital VLSI Verification Interview 第四章

    目录 Hardware Description Languages Verilog SystemVerilog 对Cracking Digital VLSI Verification Intervie ...

  9. 京东云数据库 RDS助力企业便捷运维

    iPhone6发布那年,京东在国贸等商圈送货最快速度数分钟,包括从下单到送达.这是一个极端的富含营销因素例子.即便如此,常态来看,隔天到货的这种业务模式,也是基于同样的支撑:营销业务.物流业务,大数据 ...

  10. vimdiff换行

    两个比较文件同时换行,用:windo set wrap, 或者如下 vimdiff +"windo set wrap" chap/abstract.tex abstract.tex ...