Caffeine getIfPresent()返回 null 問題
問題
集成 Caffeine 時, 將 Cache 注冊為全局的 Bean, 然后通過@Autowired 自動裝配
使用 cache.put(key, val) 和 cache.getIfPresent(key) 放入和獲取緩存
@Configuration
public class CaffeineConfig {
@Bean
public Cache<String, Object> cache() {
return Caffeine.newBuilder()
// 數量
.maximumSize(1024)
.expireAfterWrite(30, TimeUnit.MINUTES)
// 弱引用
.weakKeys()
.weakValues()
// 刪除監聽事件
.removalListener(
(RemovalListener<String, Object>) (key, val, reason) ->
System.out.println("key:" + key + ", val:" + val + ", reason:" + reason)
).build();
}
}
@RestController
public class CaffeineController {
private final Cache<String, Object> cache;
@Autowired
public CaffeineController(Cache<String, Object> cache) {
this.cache = cache;
}
@PostMapping("/add")
public Result add(String key, String val) {
cache.put(key, val);
return Result.success("add success");
}
@GetMapping
public Result get(String key) {
return Result.success((String) cache.getIfPresent(key));
}
}
無論如何調用, get()總是返回 null, 最后找到問題所在, 是配置的 Bean 有問題。
在構造 Bean 時添加了參數.weakKeys()[1], 使 key 成為弱引用變量, 被垃圾回收器發現之后就會被回收掉
key被回收掉之后獲取緩存時要使用==
(比較地址)而不是equals()
(比較值)來獲取緩存[2]。
去掉.weakKeys()之后, 可以成功取得緩存!
參考
[1] getIfPresent caffeine return null, https://stackoverflow.com/questions/63068085/getifpresent-caffeine-return-null
[2] Caffeine 緩存, xiaolyuh, https://www.jianshu.com/p/9a80c662dac4