日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深度理解springboot集成cache缓存之源码解析

發布時間:2024/10/5 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度理解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源碼

static class CacheConfigurationImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {CacheType[] types = CacheType.values();String[] imports = new String[types.length];for (int i = 0; i < types.length; i++) {imports[i] = CacheConfigurations.getConfigurationClass(types[i]);}return imports;}}}

打上斷點,debug模式下運行

放行,查看return imports的結果


導入的組件如下

* "org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration"* "org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration"

2.是哪個緩存配置類生效呢?根據當前的場景進行分析

有兩種方法可以得出哪個緩存配置類生效

第一種:源碼分析(該方法只做簡單說明)
隨便打開一個緩存配置類,例如第一個GenericCacheConfiguration,查看源碼如下

@Configuration(proxyBeanMethods = false) @ConditionalOnBean(Cache.class) @ConditionalOnMissingBean(CacheManager.class) @Conditional(CacheCondition.class) class GenericCacheConfiguration {@BeanSimpleCacheManager cacheManager(CacheManagerCustomizers customizers, Collection<Cache> caches) {SimpleCacheManager cacheManager = new SimpleCacheManager();cacheManager.setCaches(caches);return customizers.customize(cacheManager);}}

根據類上的
@ConditionalOnBean(Cache.class)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
注解進行判斷該類是否生效
這些都是@Conditional注解的衍生注解,該注解是Spring4新推出的注解,判斷是否滿足某種條件,如果滿足則給容器注冊bean

第二種:查看自動配置報告
在application.properties配置文件中添加

debug=true

運行發現這幾個組件中只有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,然后將其放到緩存中

protected Cache createConcurrentMapCache(String name) {SerializationDelegate actualSerialization = this.isStoreByValue() ? this.serialization : null;return new ConcurrentMapCache(name, new ConcurrentHashMap(256), this.isAllowNullValues(), actualSerialization);} }

可以看出返回時創建了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缓存之源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。