spring cache 概念
從spring 3.1版本開始,提供了一種透明的方式來為現有的spring 應用添加cache,使用起來就像@transaction一樣。在應用層面與后端存儲之間,提供了一層抽象,這層抽象目的在于封裝各種可插拔的后端存儲( ehcache guava redis),最小化因為緩存給現有業務代碼帶來的侵入。
spring 的緩存技術還具備相當的靈活性。不僅能夠使用 spel(spring expression language)來定義緩存的 key 和各種 condition,還提供開箱即用的緩存暫時存儲方案,也支持和主流的專業緩存比如 ehcache 集成。
其特點總結例如以下:
- 通過少量的配置 annotation 凝視就可以使得既有代碼支持緩存
- 支持開箱即用 out-of-the-box,即不用安裝和部署額外第三方組件就可以使用緩存
- 支持 spring express language,能使用對象的不論什么屬性或者方法來定義緩存的 key 和 condition
- 支持 aspectj,并通過事實上現不論什么方法的緩存支持
- 支持自己定義 key 和自己定義緩存管理者,具有相當的靈活性和擴展性
設計理念
正如spring框架的其它服務一樣,spring cache 首先是提供了一層抽象,核心抽象主要體現在兩個接口上
org.springframework.cache.cache
org.springframework.cache.cachemanager
cache代表緩存本身
cachemanager代表對緩存的處理和管理等。抽象的意義在于屏蔽實現細節的差異和提供擴展性,這一層cache的抽象解耦了緩存的使用和緩存的后端存儲,這樣后續可以方便的更換后端存儲。
使用spring cache分三步:
- 聲明緩存
- 開啟spring的cache功能
- 配置后端的存儲
聲明緩存
1
2
|
@cacheable ( "books" ) public book findbook(isbn isbn) {...} |
用法很簡單,在方法上添加@cacheable等注解,表示緩存該方法的結果。
當方法有被調用時,先檢查cache中有沒有針對該方法相同參數的調用發生過,如果有,從cache中查詢并返回結果。如果沒有,則執行具體的方法邏輯,并把結果緩存到cache中。當然這一系列邏輯對于調用者來說都是透明的。其它的緩存操作的注解包含如下(詳細說明可參見官方文檔):
- @cacheable triggers cache population
- @cacheevict triggers cache eviction
- @cacheput updates the cache without interfering with the method execution
- @caching regroups multiple cache operations to be applied on a method
- @cacheconfig shares some common cache-related settings at class-level
開啟spring cache的支持
1
|
<cache:annotation-driven /> |
或者使用注解@enablecaching的方式
配置緩存后端存儲
spring cache提供了幾種內置的后端存儲的實現:下面都是cachemanager的具體實現。
此外,spring data提供了兩個緩存管理器:
- rediscachemanager(來自于spring data redis項目)
- gmfirecachemanager(來自于spring data gemfire項目
假如使用memcached或者redis等分布式緩存的話,可以自己實現cache和cachemanager,然后在context里聲明即可。如果需要使用到多種不同的緩存實現,可以用組合模式把各種不同的cachemanager封裝在一起。
緩存的key是如何生成
我們都知道緩存的存儲方式一般是key value的方式,那么在spring cache里,key是如何被設置的呢,在這里要引入keygenerator,它負責key的生成策略,默認的使用simplekeygenerator
能看出來,其中就是有序參數數組的hash值。當然用戶可以自定義key生成策略。
spring cache的實現
上面是spring cache的大致使用方式,來看是spring是如何實現的。
在學習spring源碼的時候,有兩點可以記住:
- 大多數高級功能的實現都依賴spring aop
- 大多數功能的組裝時機都依賴sprin bean生命周期中的幾個回調接口
記住了這些就比較容易理解spring中的一些組件的實現及運行時機制
spring cache也不例外,它是典型的spring aop實現,在spring里,aop可以簡單的理解為代理(aspectj除外),我們聲明了@cacheable的方法的類,都會被代理,在代理中,實現緩存的查詢與設置操作。
cache 基礎設施的創建
上一篇(spring aop 模塊概述)談到過,spring aop的創建過程,本質是實現了一個beanpostprocessor,在創建bean的過程中創建proxy,并且為proxy綁定所有適用于該bean的advisor,最終暴露給容器。
spring中aop主幾個關鍵的概念 advisor advice pointcut
advice = 切面攔截中插入的行為
pointcut = 切面的切入點
advisor = advice + pointcut
spring cache也同樣與其它aop有類似的過程
創建 cache proxy
- 由infrastructureadvisorautoproxycreator負責的,它實現beanpostprocessor所以可以在bean實例化返回給容器前有機會創建代理,它又繼承了abstractadvisorautoproxycreator,所以又具備了給代理類綁定advisor的能力。
- pointcut的職責是由cacheoperationsourcepointcut完成的,它主要是通過方法上的cache相關的注解來判斷匹配是否需要切入
cache的攔截行
spring cache中生成cache代理對象使用的是cacheproxyfactorybean工廠類。一般來說,在spring中標準代理的創建都是基于proxyfactorybean,在這里,為了更方便的處理cache邏輯,spring引入了cacheproxyfactorybean來專門表示cache相關的代理,cache proxy能wrapper單例目標對象,并且代理目標對象實現的所有接口。
可以看到,在cacheproxyfactorybean中,有個重要的屬性是cacheinterceptor,這個類是一個methodinterceptor的實現類,這個類的職責是在目標對象目標方法上執行具體緩存操作,這也就是上面提到的advice的職責。
繼續往下跟,return 的execute方法是父類cacheaspectsupport中的方法
在這個方法里,我們最終找到的操作緩存的最終邏輯
- 判斷緩存條件
- 獲取key
- 獲取cache
-
最終調用cache.get(key, callable)方法,第二個參數是一個回調,用于處理沒有命中緩存的情況:
if cached, return; otherwise create, cache and return
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:https://mp.weixin.qq.com/s/mgC190U08WDIUEFEFM-1SA