目錄
一、本地快取介紹
二、快取元件 Caffeine 介紹
Caffeine 效能
Caffeine 配置說明
軟引用與弱引用
三、SpringBoot 整合 Caffeine 兩種方式
四、SpringBoot 整合 Caffeine 方式一
Maven 引入相關依賴
配置快取配置類
定義測試的實體物件
定義服務介面類和實現類
測試的 Controller 類
五、SpringBoot 整合 Caffeine 方式二
Maven 引入相關依賴
配置快取配置類
定義測試的實體物件
定義服務介面類和實現類
測試的 Controller 類
環境配置:
JDK 版本:1。8
Caffeine 版本:2。8。0
SpringBoot 版本:2。2。2。RELEASE
參考地址:
https://www。jianshu。com/p/c72fb0c787fc
https://www。cnblogs。com/rickiyang/p/11074158。html
博文示例專案 Github 地址:https://github。com/my-dlq/blog-example/tree/master/springboot/springboot-caffeine-cache-example
一、本地快取介紹
快取在日常開發中啟動至關重要的作用,由於是儲存在記憶體中,資料的讀取速度是非常快的,能大量減少對資料庫的訪問,減少資料庫的壓力。
之前介紹過 Redis 這種 NoSql 作為快取元件,它能夠很好的作為分散式快取元件提供多個服務間的快取,但是 Redis 這種還是需要網路開銷,增加時耗。本地快取是直接從本地記憶體中讀取,沒有網路開銷,例如秒殺系統或者資料量小的快取等,比遠端快取更合適。
二、快取元件 Caffeine 介紹
按 Caffeine Github 文件描述,Caffeine 是基於 JAVA 8 的高效能快取庫。並且在 spring5 (springboot 2。x) 後,spring 官方放棄了 Guava,而使用了效能更優秀的 Caffeine 作為預設快取元件。
1、Caffeine 效能
可以透過下圖觀測到,在下面快取元件中 Caffeine 效能是其中最好的。
2、Caffeine 配置說明
注意:
weakValues 和 softValues 不可以同時使用。
maximumSize 和 maximumWeight 不可以同時使用。
expireAfterWrite 和 expireAfterAccess 同事存在時,以 expireAfterWrite 為準。
3、軟引用與弱引用
軟引用:如果一個物件只具有軟引用,則記憶體空間足夠,垃圾回收器就不會回收它;如果記憶體空間不足了,就會回收這些物件的記憶體。
弱引用:弱引用的物件擁有更短暫的生命週期。在垃圾回收器執行緒掃描它所管轄的記憶體區域的過程中,一旦發現了只具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體
// 軟引用Caffeine。newBuilder()。softValues()。build();// 弱引用Caffeine。newBuilder()。weakKeys()。weakValues()。build();
三、SpringBoot 整合 Caffeine 兩種方式
SpringBoot 有倆種使用 Caffeine 作為快取的方式:
方式一:直接引入 Caffeine 依賴,然後使用 Caffeine 方法實現快取。
方式二:引入 Caffeine 和 Spring Cache 依賴,使用 SpringCache 註解方法實現快取。
下面將介紹下,這倆中整合方式都是如何實現的。
四、SpringBoot 整合 Caffeine 方式一
1、Maven 引入相關依賴
<?xml version=“1。0” encoding=“UTF-8”?>
2、配置快取配置類
import com。github。benmanes。caffeine。cache。Cache;import com。github。benmanes。caffeine。cache。Caffeine;import org。springframework。context。annotation。Bean;import org。springframework。context。annotation。Configuration;import java。util。concurrent。TimeUnit;@Configurationpublic class CacheConfig { @Bean public Cache
3、定義測試的實體物件
import lombok。Data;import lombok。ToString;@Data@ToStringpublic class UserInfo { private Integer id; private String name; private String sex; private Integer age;}
4、定義服務介面類和實現類
UserInfoService
import mydlq。club。example。entity。UserInfo;public interface UserInfoService { /** * 增加使用者資訊 * * @param userInfo 使用者資訊 */ void addUserInfo(UserInfo userInfo); /** * 獲取使用者資訊 * * @param id 使用者ID * @return 使用者資訊 */ UserInfo getByName(Integer id); /** * 修改使用者資訊 * * @param userInfo 使用者資訊 * @return 使用者資訊 */ UserInfo updateUserInfo(UserInfo userInfo); /** * 刪除使用者資訊 * * @param id 使用者ID */ void deleteById(Integer id);}
UserInfoServiceImpl
import com。github。benmanes。caffeine。cache。Cache;import lombok。extern。slf4j。Slf4j;import mydlq。club。example。entity。UserInfo;import mydlq。club。example。service。UserInfoService;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。stereotype。Service;import org。springframework。util。StringUtils;import java。util。HashMap;@Slf4j@Servicepublic class UserInfoServiceImpl implements UserInfoService { /** * 模擬資料庫儲存資料 */ private HashMap
5、測試的 Controller 類
import mydlq。club。example。entity。UserInfo;import mydlq。club。example。service。UserInfoService;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。web。bind。annotation。*;@RestController@RequestMappingpublic class UserInfoController { @Autowired private UserInfoService userInfoService; @GetMapping(“/userInfo/{id}”) public Object getUserInfo(@PathVariable Integer id) { UserInfo userInfo = userInfoService。getByName(id); if (userInfo == null) { return “沒有該使用者”; } return userInfo; } @PostMapping(“/userInfo”) public Object createUserInfo(@RequestBody UserInfo userInfo) { userInfoService。addUserInfo(userInfo); return “SUCCESS”; } @PutMapping(“/userInfo”) public Object updateUserInfo(@RequestBody UserInfo userInfo) { UserInfo newUserInfo = userInfoService。updateUserInfo(userInfo); if (newUserInfo == null){ return “不存在該使用者”; } return newUserInfo; } @DeleteMapping(“/userInfo/{id}”) public Object deleteUserInfo(@PathVariable Integer id) { userInfoService。deleteById(id); return “SUCCESS”; }}
五、SpringBoot 整合 Caffeine 方式二
1、Maven 引入相關依賴
<?xml version=“1。0” encoding=“UTF-8”?>
2、配置快取配置類
@Configurationpublic class CacheConfig { /** * 配置快取管理器 * * @return 快取管理器 */ @Bean(“caffeineCacheManager”) public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager。setCaffeine(Caffeine。newBuilder() // 設定最後一次寫入或訪問後經過固定時間過期 。expireAfterAccess(60, TimeUnit。SECONDS) // 初始的快取空間大小 。initialCapacity(100) // 快取的最大條數 。maximumSize(1000)); return cacheManager; }}
3、定義測試的實體物件
@Data@ToStringpublic class UserInfo { private Integer id; private String name; private String sex; private Integer age;}
4、定義服務介面類和實現類
服務介面
import mydlq。club。example。entity。UserInfo;public interface UserInfoService { /** * 增加使用者資訊 * * @param userInfo 使用者資訊 */ void addUserInfo(UserInfo userInfo); /** * 獲取使用者資訊 * * @param id 使用者ID * @return 使用者資訊 */ UserInfo getByName(Integer id); /** * 修改使用者資訊 * * @param userInfo 使用者資訊 * @return 使用者資訊 */ UserInfo updateUserInfo(UserInfo userInfo); /** * 刪除使用者資訊 * * @param id 使用者ID */ void deleteById(Integer id);}
服務實現類
import lombok。extern。slf4j。Slf4j;import mydlq。club。example。entity。UserInfo;import mydlq。club。example。service。UserInfoService;import org。springframework。cache。annotation。CacheConfig;import org。springframework。cache。annotation。CacheEvict;import org。springframework。cache。annotation。CachePut;import org。springframework。cache。annotation。Cacheable;import org。springframework。stereotype。Service;import org。springframework。util。StringUtils;import java。util。HashMap;@Slf4j@Service@CacheConfig(cacheNames = “caffeineCacheManager”)public class UserInfoServiceImpl implements UserInfoService { /** * 模擬資料庫儲存資料 */ private HashMap
5、測試的 Controller 類
import mydlq。club。example。entity。UserInfo;import mydlq。club。example。service。UserInfoService;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。web。bind。annotation。*;@RestController@RequestMappingpublic class UserInfoController { @Autowired private UserInfoService userInfoService; @GetMapping(“/userInfo/{id}”) public Object getUserInfo(@PathVariable Integer id) { UserInfo userInfo = userInfoService。getByName(id); if (userInfo == null) { return “沒有該使用者”; } return userInfo; } @PostMapping(“/userInfo”) public Object createUserInfo(@RequestBody UserInfo userInfo) { userInfoService。addUserInfo(userInfo); return “SUCCESS”; } @PutMapping(“/userInfo”) public Object updateUserInfo(@RequestBody UserInfo userInfo) { UserInfo newUserInfo = userInfoService。updateUserInfo(userInfo); if (newUserInfo == null){ return “不存在該使用者”; } return newUserInfo; } @DeleteMapping(“/userInfo/{id}”) public Object deleteUserInfo(@PathVariable Integer id) { userInfoService。deleteById(id); return “SUCCESS”; }}