基于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、应用案例:
基于Redis的Service缓存实现的更多相关文章
- 基于redis的分布式缓存disgear开源到github上了
disgear是笔者参考solrcloud架构基于redis实现的分布式的缓存,支持数据切分到多台机器上,支持HA,支持读写分离和主节点失效自动选举,目前把它开放到github上,开放给大家 gith ...
- Govern Service 基于 Redis 的服务治理平台
Govern Service 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心) Govern Service 是一个轻量级.低成本的服务注册.服务发现. 配置服务 SDK,通过 ...
- 基于Spring接口,集成Caffeine+Redis两级缓存
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 在上一篇文章Redis+Caffeine两级缓存,让访问速度纵享丝滑中,我们介绍了3种整合Caffeine和Redis作为两级缓存使用的方法,虽 ...
- 基于redis分布式缓存实现(新浪微博案例)
第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的API. 第二:出现背景 数据结构(Data Structure)需求越来 ...
- .NET基于Redis缓存实现单点登录SSO的解决方案[转]
一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...
- .NET基于Redis缓存实现单点登录SSO的解决方案
一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...
- 基于redis分布式缓存实现
Redis的复制功能是完全建立在之前我们讨论过的基 于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你 的 ...
- 基于Redis缓存的Session共享(附源码)
基于Redis缓存的Session共享(附源码) 在上一篇文章中我们研究了Redis的安装及一些基本的缓存操作,今天我们就利用Redis缓存实现一个Session共享,基于.NET平台的Seesion ...
- redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现
本次分享如何使用redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现思路 现在的互联网公司大多数都是以Redis作为缓存,使用缓存的优点就不赘述了,写这篇文章的目的就是想帮助同学们如 ...
随机推荐
- HTTP协议(四):首部
前言 作者说:上一节中介绍了HTTP报文中的状态码,这一节同样是对报文的补充,介绍的是HTTP首部字段.不过,你如果是第一次见到这个东西,肯定会特别疑惑,什么是HTTP首部? <图解HTTP&g ...
- [备忘]js表单序列化代码
function serialize(form) { var parts = [], elems = form.elements, i = 0, len = elems.length, filed = ...
- delphi save .dfm to .txt
procedure TForm2.saveDfm; var inStream,outStream:TMemoryStream; begin inStream:=TMemoryStream.Create ...
- oracle 向表中插入BLOB类型数据
提示: 待插入图片必须保存到oracle主机路径上. 步骤: 1.SYSDBA权限用户创建图片所在目录 CREATE OR REPLACE DIRECTORY TEST_DIR AS 'C:\Pict ...
- WOJ 1546 Maze 图论上的状态压缩DP
http://acm.whu.edu.cn/land/problem/detail?problem_id=1546 这个题目还是聪哥教的方法过的 首先搜索是必须的,而且通过搜索来缩点,这些应该要想到, ...
- 2020/1/28 PHP代码审计之命令执行漏洞
0x00 命令执行漏洞原理 应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system.exec.shell_exec.passthru.popen.proc_popen等函数可以执行 ...
- 关于scala工程结构(使用sbt)
scala_project:常用目录结构: |lib:手动添加依赖包 |project | |build.properties:build的版本号,可以不写,会自动下载 | |plugins.sbt: ...
- Azure App Service-添加自定义域名和SSL保护
语雀知识库:https://www.yuque.com/seanyu/azure/appservicessl 公众号:云计算实战 案例 添加自定义域并开启SSL保护 进入App Service控制台 ...
- oi笔记——抽象的深度优先搜索
oi笔记--抽象的深度优先搜索 例题: \(N个数中选K个数,选出的和要为sum\) 例题分析: 对于每个点,我们可以按"选"和"不选"进行搜索,如图: 或者0 ...
- offer(背包问题、DP)
蒜头君很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了.要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的.蒜头君没有多少钱,总共只攒了n万元 ...