AOP实现redis缓存
redis使用AOP实现记录缓存, 可以大大减少代码量, 提高工作效率
1. 配置redis
1.1配置文件
创建一个redis.properties
# 配置单台redis
redis.host=192.168.126.129
redis.port=6379
1.2编辑配置类
@Configuration //标识我是配置类
@PropertySource("classpath:/properties/redis.properties") // 读取配置文件
public class RedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
//数据写死?????????
return new Jedis(host,port);
}
}
2. 自定义注解
在指定的方法上使用, 把方法执行的结果使用AOP自动解析为json并存入redis 缓存
@Target(ElementType.METHOD) //注解在方法中使用
@Retention(RetentionPolicy.RUNTIME) //运行期有效
public @interface CacheFind {
String key(); //1.设定key 用户自己设定
int seconds() default 0; //2.可以指定超时时间,也可以不指定.
}
3. AOP实现redis缓存
@Component //1.我是一个javaBean
@Aspect //2.我是一个切面
public class CacheAOP {
//引入redis缓存配置
@Autowired
private Jedis jedis;
/**
* AOP缓存实现的业务策略
* 1.切入点表达式应该拦截 @CacheFind注解
* 2.通知方法: 环绕通知
* 注意事项: 如果使用环绕通知,则必须在第一个参数的位置添加 ProceedingJoinPoint
*
* 动态获取注解参数的步骤:
* 1.@annotation(cacheFind) 切入点表达式要求拦截一个类型为cacheFind注解.
* 2.并且利用连接点为参数中的cacheFind赋值.
* */
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
try {
// 目标方法执行的返回结果
Object result = null;
//1.如何动态获取注解中的数据
String prekey = cacheFind.key();
//2.动态获取方法中的参数 将数组转化为字符串
String args = Arrays.toString(joinPoint.getArgs());
String key = prekey + "::" + args;
//3.检验redis中是否有数据
if(jedis.exists(key)){
//有缓存 从redis缓存中获取json 之后还原对象返回
String json = jedis.get(key);
//target代表这目标方法的返回值类型......
//动态获取目标方法的返回值类型?? 向上造型 不用强转 向下造型
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Class returnClass = methodSignature.getReturnType();
//将json数据转化为对象
result = ObjectMapperUtil.toObject(json, returnClass);
System.out.println("AOP实现缓存查询!!!!");
}else{
//第一次查询数据库.
result = joinPoint.proceed(); //执行目标方法.
System.out.println("AOP执行数据库操作");
//2.将数据保存到redis中
String json = ObjectMapperUtil.toJSON(result);
if(cacheFind.seconds()>0) //表示需要设定超时时间
jedis.setex(key, cacheFind.seconds(), json);
else
//不需要超时
jedis.set(key, json);
}
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
throw new RuntimeException(throwable); //将检查异常,转化为运行时异常
}
}
}
4. 测试
假设下面为service层的方法
@CacheFind(key = "FIND_NAME")
public String findName() {
return "hello world";
}
在controller中调用, 多次请求此controller的结果
AOP执行数据库操作
AOP实现缓存查询!!!!
AOP实现缓存查询!!!!
AOP实现缓存查询!!!!
......