利用AOP中采用注解的形式实现业务缓存处理
通知选择:环绕通知.利用注解定义切入点表达式.
业务思路:当执行方法时如果该方法添加了@Cache()则进行AOP业务执行.
首先根据key(????)查询redis缓存.
null: 应该执行业务方法.,获取返回值之后添加缓存.
!null:将缓存数据转化为返回值对象.之后返回.
通用做法:
key:按照方法名称+第一个参数拼接动态的Key
findAll();
//定义一个查询的注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD}) //注解的作用范围
public @interface Cache_Find {
String key() default "";//接收用户key值
KEY_ENUM keyType() default KEY_ENUM.AUTO;//定义key类型
int secondes() default 0; //永不失效
}
编辑AOP
@Component //将对象交给spring容器管理
@Aspect //标识这是一个切面 切面=切入点表达式+通知
@Slf4j
public class RedisAspect {
//表示当spring容器启动时不会立即注入对象???
@Autowired(required = false)
private JedisCluster jedisCluster;
/**
*规定:
* 1.环绕通知必须使用ProceedingJoinPoint
* 2.如果通知中有参数joinPoint.必须位于第一位
* @param joinPoint
* @return
*/
@SuppressWarnings("unchecked")
//问题1:如何获取注解中的属性?
//该切入点表达式 规定只能获取注解类型 用法名称必须匹配
@Around(value="@annotation(cache_Find)")
public Object around(ProceedingJoinPoint joinPoint,Cache_Find cache_Find) {
//1.动态获取key
String key = getKey(joinPoint,cache_Find);
//2.从redis中获取数据
String resultJSON = jedisCluster.get(key);
Object resultData = null;
try {
//3.判断数据是否有值
if(StringUtils.isEmpty(resultJSON)) {
//3.1表示缓存中没有数据,则查询数据库(调用业务方法)
resultData = joinPoint.proceed();
//3.2将数据保存到缓存中
String json = ObjectMapperUtil.toJSON(resultData);
//3.3判断当前数据是否有失效时间
if(cache_Find.secondes()==0) {
jedisCluster.set(key, json);
}else {
jedisCluster.setex(key,cache_Find.secondes(), json);
}
System.out.println("AOP查询数据库成功!!!");
}else {
//4.表示redis缓存中有数据
Class returnType = getClass(joinPoint);
resultData = ObjectMapperUtil.toObject(resultJSON,returnType);
System.out.println("AOP查询缓存!!!!!!");
}
} catch (Throwable e) {
e.printStackTrace();
log.error(e.getMessage());
throw new RuntimeException(e);
}
return resultData;
}
key的定义
/**
* key的定义规则如下:
* 1.如果用户使用AUTO.则自动生成KEY 方法名_第一个参数
* 2.如果用户使用EMPTY,使用用户自己的key
* @param joinPoint
* @param cache_Find
* @return
*/
private String getKey(ProceedingJoinPoint joinPoint, Cache_Find cache_Find) {
//1.判断用户选择类型
if(KEY_ENUM.EMPTY.equals(cache_Find.keyType())) {
return cache_Find.key();
}
//2.表示用户动态生成key findITemCat::0
String methodName = joinPoint.getSignature().getName();
String arg0 = String.valueOf(joinPoint.getArgs()[0]);
return methodName+"::"+arg0;
}
/**
*表示获取方法对象的返回值类型
* @param joinPoint
* @return
*/
private Class getClass(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
return signature.getReturnType();
}
}