最近寫一個小項目,遇到一個高頻查詢功能,使用redis又有點浪費,就決定採用本地緩存來實現,於是就想到了一直很火的GuavaCache,這裏對使用GuavaCache做一些小結。
(在查資料的過程中,發現springBoot 2.x版本中已經移除了GuavaCache的支持,改用了Caffeine,這個需要抽空看看了)
整合起來很簡單,具體如下:
LoadingCache<String, Integer> LOGIN_CACHE = CacheBuilder.newBuilder()
.maximumSize(100) // 設置緩存的最大容量
.expireAfterWrite(5, TimeUnit.SECONDS) // 測試用,5秒後失效
.concurrencyLevel(10) // 設置併發級別爲10
.recordStats() // 開啓緩存統計,生產不建議使用
.removalListener(notification -> log.info(notification.getKey() + " " + notification.getValue() + " 被移除,原因:" + notification.getCause()))
.build(new UserInfoLoad());
public class UserInfoLoad extends CacheLoader<String, Integer> {
@Override
public Integer load(String key) {
UserInfoExample userInfoExample = new UserInfoExample();
userInfoExample.createCriteria().andUuidEqualTo(key);
List<UserInfo> userInfos = userInfoMapper.selectByExample(userInfoExample);
if (CollectionUtils.isEmpty(userInfos)) {
return 0;
}
return userInfos.get(0).getId();
}
}
可以看到代碼中我增加了removalListener,是爲了驗證一個問題:guavaCache只有在被觸發時纔會進行過期緩存清理,極端情況下,如果緩存很多以後,不再有方法觸發它,那就會造成內存泄露了。不過這個極端情況幾乎不會發生,設計的時候注意一下即可。
這裏還遇到了第一個比較蠢得問題,我一開始將這個方法寫在了service的方法內,結果每次調用都會查庫,沒有實現緩存的效果,反應了好一陣纔想起來應該把這段代碼移出方法體,哎。
然後我又想把這段邏輯做成一個靜態方法類,這樣所有需要獲取用戶信息的方法都可以調用。這樣做本身是沒任何問題的,但是執行的時候,會報userInfoMapper空指針異常,查詢相關資料才發現原來spring不會注入靜態屬性。靜態屬性需要手動注入set方法。
private static UserInfoMapper userInfoMapper;
@Autowired
public void setUserInfoMapper(UserInfoMapper userInfoMapper) {
UserCache.userInfoMapper= userInfoMapper;
}
這樣一個簡單的GuavaCache實現就做好了。小型項目,或者配置不高的情況下,確實沒必要安裝那麼多中間件,可以本地實現的話最好不過了。