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實現緩存查詢!!!!
......