背景
现在程序中是直接查询数据库数据的,Redis只是用来生成一些不重复id用的,现在要把Redis利用起来,缓存一些配置信息,提高程序运行及响应时间。
设计
- 在Dao层查询数据库之前,先查一下是否在Redis缓存中,如果存在的话直接取Redis中的数据,如果不存在,在去查询数据库,然后将本次查询结果根据查询条件放到缓存中。
- Redis在系统启动的时候先去清空配置信息。
- 提供刷新缓存、删除缓存的方法
实现之前
在Dao层中每个查询配置信息的方法中,增加查询缓存及设置缓存的方法。
但是Dao层中的方法太多了。。。一个个加比较枯燥、主要是显得比较low,然后要想个方案实现。
方案
很自然就想到了AOP,环绕通知,
在目标方法执行之前先查询缓存,如果有就返回了,如果没有再去执行目标方法,
在执行目标方法之后将查询条件及内容放到Redis中。
自定义一个注解,被这个注解修饰的方法需要实现AOP。
实现
定义一个缓存注解,被这个注解修饰的方法,会执行切面中的方法。
/**
* redis缓存注解
* @author hitol
* @version $Id: RedisCache.java, v 0.1 2020年3月19日 下午8:26:48 hitol Exp $
*/
@Documented
@Target({java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCache {
String redisKey() default "";
String cacheInfo() default "";
Class<?> className() default String.class;
}
定义缓存切面,使用环绕通知.
/**
* 缓存切面
* @author hitol
* @version $Id: CacheAop.java, v 0.1 2020年3月20日 下午6:49:10 hitol Exp $
*/
@Aspect
@Component
public class CacheAop {
private static final Logger LOGGER = LoggerFactory.getLogger(CacheAop.class);
@Pointcut("@annotation(com.acc.ac.core.util.redis.RedisCache)")
public void getCacheInfo() {
LOGGER.info("切入点");
}
@Around("getCacheInfo()")
public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
// 接口的参数
Object[] args = joinPoint.getArgs();
String arg = "";
if (args.length > 0){
arg = (String) args[0];
}
// 得到被代理的方法
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
// 得到被代理的方法上的注解
RedisCache annotation = method.getAnnotation(RedisCache.class);
Class<?> className = annotation.className();
String redisKey = annotation.redisKey() + arg;
Class returnType = method.getReturnType();
LOGGER.info("key = {},查询Redis缓存", redisKey);
String cacheInfo = RedisUtils.getString(redisKey);
if (StringUtils.isNotBlank(cacheInfo)) {
LOGGER.info("key = {},在Redis缓存中.", redisKey);
if ("java.util.List".equals(returnType.getName())){
return JSONObject.parseArray(cacheInfo,className);
}
return JSONObject.parseObject(cacheInfo, returnType);
}
LOGGER.info("key = {},没有在Redis缓存中查询到.", redisKey);
Object result = joinPoint.proceed(args);
cacheInfo = JSONObject.toJSONString(result);
if (StringUtils.isNotBlank(cacheInfo)) {
RedisUtils.setString(redisKey, cacheInfo);
}
return JSONObject.parseObject(cacheInfo, returnType);
}
}
完成。