上篇文章实现了redis的通用缓存,但是用起来不是很灵活,用within表达式,使得service的每个业务都用到了缓存。
如果想要指定哪些方法上用缓存,哪些不用该怎么设计?
例如:在UserServiceImpl实现类中有findAll和findOne两个方法,我想要在查询所有findAll这一部分添加缓存,而findOne不加入缓存。
这就要用到自定义注解来设计,有关自定义注解可以参考:https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html
设计思路:
1.首先设计一个RedisCache自定义注解这样一个类。
/* 自定义注解,value = ElementType.METHOD表示该注解用在方法上 */ @Target(value = ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RedisCache { public String value(); }
2.这样的自定义注解类用在哪个方法上,就在该方法上写 @RedisCache("value")
3.在切面类中判断,业务层方法上有自定义注解RedisCache,然后执行缓存操作,否则就什么也不做
@Around("execution(* com.lkl.service.*ServiceImpl.find*(..))")
public Object around(ProceedingJoinPoint pjp){
//判断当前切入的方法上是否存在rediscache这个注解
MethodSignature signature1 = (MethodSignature) pjp.getSignature();
Method method = signature1.getMethod();//先获取方法对象
//判断有没有RedisCache这个注解
boolean isHaveAnnotation = method.isAnnotationPresent(RedisCache.class);
if (isHaveAnnotation){ //切入的方法上有这个注解,执行切面操作
//获取key
String key = getKey(pjp);
//获取jedis对象,以默认端口号6379连接
Jedis jedis = new Jedis("192.168.1.*",6379);
Object result = null;
//判断Redis中是否存在这个key
if(jedis.exists(key)){//如果存在取出数据返回
System.out.println("the data is exist in redis,direct return ");
String json = jedis.get(key);
//把这个签名,转换为反射包中的MethodSignature
MethodSignature signature = signature1;
System.out.println(signature.getReturnType());
result = JSONObject.parseObject(json,signature.getReturnType());
}else{ //如果不存在,放行Dao方法执行存入Redis中
System.out.println("the data is not exist in redis,query the DB");
try {
result = pjp.proceed();//放行
//放入redis中,以json形式存入
jedis.set(key,JSONObject.toJSONString(result));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
return result;
}else { //没有这个注解什么也不做,直接放行
Object proceed = null;
try {
proceed = pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return proceed;
}
}