javascript
Springboot中的缓存Cache和CacheManager原理介绍
一、背景理解
- 什么是緩存,為什么要用緩存?
程序運行中,在內(nèi)存保持一定時間不變的數(shù)據(jù)就是緩存。簡單到寫一個Map,里面放著一些key,value數(shù)據(jù),就已經(jīng)是個緩存了。所以緩存并不是什么高大上的技術(shù),只是個概念,把要多次使用的東西存在一個變量里,時不時取出來使用,就達到了緩存的目的,緩存就是存放數(shù)據(jù)的容器。那為什么要用緩存呢,是因為要多次使用。一個程序總有一些數(shù)據(jù)是可預(yù)見被多次使用(預(yù)見的準不準就是常說的命中率)比如一個復(fù)雜的計算結(jié)果,一次數(shù)據(jù)庫訪問取得的數(shù)據(jù)等耗時耗資源的數(shù)據(jù)就能放入緩存,目的就是為了節(jié)省開銷,我們要用有限的資源(CPU,內(nèi)存,帶寬等等)盡量做最多的事情。
二、為什么要用SpringCache(緩存的演變過程)
- 緩存的思考
如果我們要設(shè)計一個緩存,最基本的功能是存和取:
可是這不夠呀,比如以下的思考
為了讓緩存更好用,更“智能”,越來越多的需求就會被提出來,而緩存就是這樣一步步演變直到SpringCache橫空出世,功能十分強大(說白了就是我們少寫很多代碼)
SpringCache包含兩個頂級接口,Cache(緩存)和CacheManager(緩存管理器),顧名思義,用CacheManager去管理一堆Cache。最最關(guān)鍵的地方:抱緊了Spring的大腿,可以使用注解就能完成數(shù)據(jù)進入緩存!!具體使用參考文章。
首先,Springboot中會自動加載一個CacheManager(它有默認的實現(xiàn)類),所以只要寫好一個自定義的Cache即可(如果想用系統(tǒng)定義好的或者第三方如RedisCache也行,記得向Spring注冊這個bean即可)
@Component public class MyCache implements Cache {/*實現(xiàn)接口方法,一些關(guān)于數(shù)據(jù)set和get的方法CacheManager是根據(jù)Cache的名字進行管理的所以假設(shè)這個Cache名為MyCache*/ }然后在得出數(shù)據(jù)的方法上寫上注釋即可
@Cacheable(value = "MyCache",key = "#id")public String getNavegationURLs(String id) {//一個獲取數(shù)據(jù)的方法}這樣就會在調(diào)用這個方法時,會以id為key值,在名為MyCache的Cache容器中查找(注解中value就是緩存名字,不同名字指定使用不同的緩存)如果沒查到,則執(zhí)行方法 getNavegationURLs,將返回值存入緩存。如果找到了,就直接將從緩存取值,直接返回,不用執(zhí)行方法 getNavegationURLs還有其他方便的Cache注解參考上面給出的參考文章,重要的是我們根本不用寫任何關(guān)于調(diào)用緩存的邏輯代碼,只用關(guān)注于緩存自身的邏輯
三、注解如何起作用的,源碼流程大致了解
最直接的原因是因為SpringCache是不支持靈活的緩存時間設(shè)置的,所以想了解大概的來龍去脈去實現(xiàn)一個支持緩存過期時間設(shè)置和自動更新的類(SpringCache自定義過期時間及自動刷新)。高大上的原因是想通過這次探索,去了解下Spring對類的管理機制,去接觸下AOP的實現(xiàn)
大家從上面例子有沒發(fā)現(xiàn)問題,Cache和CacheManager是怎樣做關(guān)聯(lián)的,其實是Spring掃包實現(xiàn)的。凡是繼承了Cache接口的類,都會被自動注入進CacheManager中,最終存儲于CacheManager的實現(xiàn)類中
接著會生成被@Cacheable(或者其他SpringCache注解修飾過)的代理類,并會將管理它的CacheManager賦值進去
看這段代碼,就知道如果要設(shè)置多個CacheManager,就得在眾多實現(xiàn)類的其中一個加上@Primary,不然會Spring會報錯能選擇的Bean太多而不知道用哪個。代理類生成后(包括會根據(jù)不同的注解生成信息類CacheOperationMetadata,到時候就會根據(jù)這個類的內(nèi)容進行緩存操作,說白了就是調(diào)用我們實現(xiàn)Cache里面的各種方法)
Springboot底層初始化完成后,進入我們寫的代碼邏輯,如果這時進入了該類的方法,如:
代碼跟進去,你會神奇的發(fā)現(xiàn)進入了代理類的intercept方法,怎么進去的呢~(具體原理看下面3.0)
這里面就會根據(jù)注解類型,進行緩存的邏輯判斷,然后決定會不會調(diào)用我們寫的方法~
四、代理類原理介紹(AOP切面之類的都是通過代理哦)
Spring代理分為兩種:
那么代理類滿足以下條件:首先實現(xiàn)一個InvocationHandler,方法調(diào)用會被轉(zhuǎn)發(fā)到該類的invoke()方法。
意思是:對代理對象的所有接口方法調(diào)用都會轉(zhuǎn)發(fā)到InvocationHandler.invoke()方法,在invoke()方法里我們可以加入任何邏輯,比如修改方法參數(shù),加入日志功能、安全檢查功能等;之后我們通過某種方式執(zhí)行真正的方法體
那么代理類滿足以下條件:
實現(xiàn)一個MethodInterceptor,方法調(diào)用會被轉(zhuǎn)發(fā)到該類的intercept()方法
具體內(nèi)容可以參考這篇精品博客:https://www.cnblogs.com/CarpenterLee/p/8241042.html
本人也寫過一篇文章可供參考
如果你想自己實現(xiàn)代理類(就是不喜歡用工具包),其實也行啊,輸出符合class規(guī)范的二進制字節(jié)碼就行啦~~~(認真學(xué)習(xí)JVM規(guī)范吧)
總結(jié)
以上是生活随笔為你收集整理的Springboot中的缓存Cache和CacheManager原理介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我们公司也实行了OKR
- 下一篇: Spring Session使用