在使用springboot開發項目的時候,我們經常會用到緩存,一般就是通過註解@Cacheable來進行緩存設置。
我們代碼是寫了@Cacheable,我們以爲能生效,但有時候因爲一些原因,導致緩存不生效,程序也能正常運行,而我們卻矇在鼓裏。如果是redis,雖然可以通過客戶端去登錄服務器查看有沒有緩存,但也十分麻煩。
爲了省點事,所以想到使用AOP來自動進行緩存檢查,如果沒有生效,就打印一些信息提示我們。
實現步驟很簡單,只需要在springboot工程中添加上一個AOP類即可,並在配置文件中添加cacheable.check.switch=1
/**
* 不要設置order,否則該AOP將會在@Cacheable之前執行,就無法檢測緩存是否起作用了
* 僅支持對方法級的@Cacheable進行檢測,默認是以方法的所有參數作爲key
* 不支持緩存緩存更新,重新緩存的情況(會判斷爲緩存失效,可以自己完善實現處理@CacheEvict)
*/
@Aspect
@Component
@ConditionalOnProperty(name = "cacheable.check.switch",havingValue = "1")
public class CacheableCheckAop {
//針對每個緩存,都有自己的一個set
private Map<String, Set<String>> cache = new ConcurrentHashMap<>();
//存放失效緩存的集合
private Set<String> unValidCache = new HashSet<>();
@Around("@annotation(cacheable)")
public Object before(ProceedingJoinPoint joinPoint, Cacheable cacheable) throws Throwable{
Object[] args = joinPoint.getArgs();
String value = String.join("_", cacheable.value());
if(!unValidCache.contains(value)) {
if (!cache.containsKey(value)) {
synchronized (cache) {
if (!cache.containsKey(value)) {
cache.put(value, new HashSet<>());
}
}
}
String key = Arrays.stream(args).map(String::valueOf).collect(Collectors.joining("_"));
Set<String> set = cache.get(value); //同一個緩存同一個key,如果多次調用了,說明緩存失效
if (set.contains(key)) {
System.err.println(value + "緩存無效,key:" + key);
unValidCache.add(value);
} else {
set.add(key);
}
}
try {
return joinPoint.proceed();
}finally {
}
}
}
緩存失效的情況:
1.工程中忘記打開@EnableCaching
2.方法調用同一個類的另一個註解了@Cacheable方法
例如上面的這些,該AOP都可以提示緩存失效,不用我們再人爲去檢查了。
總結:
通過AOP,在原有緩存基礎上,再實現我們的簡單緩存,如果相同的key,調用了兩次,就判斷爲緩存沒有起作用