深度理解springboot集成cache缓存之源码解析
一、案例準備
1.創建數據表(employee表)
2.創建Employee實體類封裝數據庫中的數據
@AllArgsConstructor @NoArgsConstructor @Data @ToString public class Employee {private Integer id;private String lastName;private String email;private Integer gender; //1.男 2.女private Integer dId; }3.編寫EmployeeMapper接口(DAO測通)
@Mapper public interface EmployeeMapper {@Select("select * from employee where id=#{id}")Employee getEmpById(Integer id); }4.編寫EmployeeService接口及其EmployeeServiceImpl實現類
@Service public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeMapper employeeMapper;@Override@Cacheable(cacheNames = "emp",key = "#id",condition = "#id>0")public Employee getEmp(Integer id) {System.out.println("正在查詢id為"+id+"號的員工");Employee emp = employeeMapper.getEmpById(id);return emp;} }5.編寫EmployeeController類
@RestController public class EmpController {@Autowiredprivate EmployeeService employeeService;@GetMapping("/emp/{id}")public Employee getEmployee(@PathVariable("id") Integer id){Employee emp = employeeService.getEmp(id);return emp;} }6.啟動訪問http://localhost:8080/emp/1
成功!
-----------------------------------------------分割線-------------------------------------------------------------
二、工作原理分析
1.查看springboot啟動時,導入了哪些緩存組件
通過以往springboot相關的自動配置類可知與緩存相關的自動配置類為CacheAutoConfiguration
@Import:向容器中導入一些組件(通常導入的選擇器以ImportSelector結尾)
ctrl+右鍵查看CacheConfigurationImportSelector源碼
打上斷點,debug模式下運行
放行,查看return imports的結果
導入的組件如下
2.是哪個緩存配置類生效呢?根據當前的場景進行分析
有兩種方法可以得出哪個緩存配置類生效
第一種:源碼分析(該方法只做簡單說明)
隨便打開一個緩存配置類,例如第一個GenericCacheConfiguration,查看源碼如下
根據類上的
@ConditionalOnBean(Cache.class)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
注解進行判斷該類是否生效
這些都是@Conditional注解的衍生注解,該注解是Spring4新推出的注解,判斷是否滿足某種條件,如果滿足則給容器注冊bean
第二種:查看自動配置報告
在application.properties配置文件中添加
運行發現這幾個組件中只有SimpleCacheConfiguration生效了
3.分析核心類的作用
進去查看SimpleCacheConfiguration的源碼
@Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(CacheManager.class) @Conditional(CacheCondition.class) class SimpleCacheConfiguration {@BeanConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties,CacheManagerCustomizers cacheManagerCustomizers) {ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();List<String> cacheNames = cacheProperties.getCacheNames();if (!cacheNames.isEmpty()) {cacheManager.setCacheNames(cacheNames);}return cacheManagerCustomizers.customize(cacheManager);}}可以看出給容器中注冊了一個ConcurrentMapCacheManager緩存管理器
查看源碼分析創建Cache的具體細節
這一段代碼是創建Cache的核心
#首先通過該類中的cacheMap屬性獲取緩存,參數為緩存名字(key-value)
#然后進行判斷,如果cache為null,則上鎖;再次獲取如果為null,則根據本類中的createConcurrentMapCache方法創建Cache,然后將其放到緩存中
可以看出返回時創建了ConcurrentMapCache對象,進去查看源碼
lookup方法的作用是從緩存中獲取數據
put方法的作用是是保存數據到緩存中
自此我們可以猜一下,ConcurrentMapCache該類的作用就是對緩存中的數據進行操作,如果緩存中沒有數據,則從數據庫查詢,一并放到緩存中
總的來說ConcurrentMapCacheManager類的作用就是,先判斷是否有某緩存,如果沒有就創建該緩存,ConcurrentMapCache類從數據庫中進行查詢,一并將數據存儲到ConcurrentMap集合中
4.運行流程
根據上面打上的四個斷點,debug模式下啟動
發現程序剛開始并沒有走EmployeeServiceImpl的斷點,而是走到了這個getCache方法,尋找name=emp的緩存
因為沒有名為emp的緩存,所以會創建名為emp的緩存,繼續放行
使用key去緩存中查找內容(key默認是方法的參數,瀏覽器訪問的是1號員工信息,id=1即key=1),size=0,緩存中的數據為空
繼續放行
直接調用業務方法去數據庫中查詢數據了,這是為什么呢,因為上個步驟在緩存中沒有查詢到數據,所以需要向數據庫中要數據;繼續放行
上一步從數據庫中查詢出數據之后,將數據傳回前端頁面展示并使用put方法將其放入到緩存中
此時緩存中已經有數據了,當我再次debug運行 就不會再從數據庫中查詢數據了
該博客僅為了記錄自己的學習過程,理清技術點思路
總結
以上是生活随笔為你收集整理的深度理解springboot集成cache缓存之源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis的基础命令操作
- 下一篇: 数据结构和算法之稀疏数组