javascript
Spring实战——缓存
緩存
提到緩存,你能想到什么?一級緩存,二級緩存,web緩存,redis……
你所能想到的各種包羅萬象存在的打著緩存旗號存在的各種技術(shù)或者實現(xiàn),無非都是宣揚緩存技術(shù)的優(yōu)勢就是快,無需反復(fù)查詢等。
當(dāng)然,這里要講的不是一級二級,也不是redis,而是Spring的緩存支持。當(dāng)時基于工作上的業(yè)務(wù)場景,考慮需要用到緩存技術(shù),但是并不清楚該用什么樣的緩存技術(shù),起初甚至有想過把信息寫到redis中,然后讀redis的信息(現(xiàn)在想想,真是小題大做),后來發(fā)現(xiàn)Spring提供了緩存的解決方案——Spring Cache。雖然最終找到了一個更加簡便討巧的方式解決了問題,但是今天還是把自己零碎的Spring Cache知識稍稍梳理下。
這里大概介紹下業(yè)務(wù)場景:
- 現(xiàn)在有功能模塊一和功能模塊二,分別負(fù)責(zé)兩件事;
- 執(zhí)行功能模塊二的時候,可以用到模塊一的執(zhí)行結(jié)果,當(dāng)然不用也可以,那就再執(zhí)行一遍;
- 讀取功能模塊一執(zhí)行后存放在Cache中的數(shù)據(jù),這時候就省去重新執(zhí)行模塊一的冗余操作
流程圖如下:
Spring Cache
有關(guān)Spring Cache的理論詳細(xì)介紹可以看官方文檔或者參閱《Spring實戰(zhàn)》第十三章,這里偏代碼實戰(zhàn)看看Spring Cache如何使用。
聲明啟用緩存
就像如果要啟用AOP需要添加
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>一樣,如果要用cache,也需要聲明
<cache:annotation-driven />這樣還不夠,除此以外,我們還需要一個緩存管理器
<bean id="cacheManager"class="org.springframework.cache.support.SimpleCacheManager"><property name="caches"><set><beanclass="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"p:name="default" /><beanclass="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"p:name="personCache" /></set></property></bean>這個緩存管理器是Spring緩存抽象的核心,可以繼承多個流行的緩存實現(xiàn)。從上面的聲明可以看出,這里聲明了ConcurrentMapCacheManager管理器,從字面就可以看出其內(nèi)容實現(xiàn)應(yīng)該是通過ConcurrentHashMap來做緩存的。(除了這個簡單的緩存管理器,當(dāng)然還有如NoOpCacheManager、EhCacheCacheManager、RedisCacheManager、CompositeCacheManager等管理器)
這里的personCache就是本例中用到的聲明的管理器
以上的xml聲明可以存放到一個spring-cache.xml中,完整內(nèi)容如下
編寫需要緩存的方法
- 在此之前,我們需要一個bean對象Person,其有id,age,name三個屬性
- 準(zhǔn)備需要緩存的接口方法
findPerson()方法很簡單,主要是根據(jù)id查找到相應(yīng)的Person對象。
這里第一行加上了打印信息,用于區(qū)分每次調(diào)用是否走緩存了。如果直接用的是緩存結(jié)果,則不會打印這句話,如果沒有緩存,則需要執(zhí)行函數(shù)體,從而打印改行顯示。
@Cacheable注解:主要用來配置方法,能夠根據(jù)方法的請求參數(shù)對其結(jié)果進(jìn)行緩存。即當(dāng)重復(fù)使用相同參數(shù)調(diào)用方法的時候,方法本身不會被調(diào)用執(zhí)行,即方法本身被略過了,取而代之的是方法的結(jié)果直接從緩存中找到并返回了。簡而言之就是如果緩存有則取出,如果沒有則執(zhí)行方法。
驗證
到此我們就可以驗證了。編寫代碼如下
public class SpringCache {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-cache.xml");// 加載 spring 配置文件PersonService personService = (PersonService) context.getBean("personService");// 第一次查詢,應(yīng)該真實查詢System.out.println(personService.findPerson(18));// 第二次查詢,應(yīng)該直接返回緩存的值System.out.println(personService.findPerson(18));} }最終執(zhí)行結(jié)果如下
real query person object info Person{id=18, age=18, name='Jackie'} Person{id=18, age=18, name='Jackie'}可以看出第一次結(jié)果顯示前打印出了real query person object info說明真實執(zhí)行了findPerson()方法;
第二次打印的結(jié)果沒有包含這行信息,說明是從緩存中直接取的數(shù)據(jù),而且通過調(diào)試打斷點確實發(fā)現(xiàn)第二次并未進(jìn)入findPerson()方法。
@CacheEvict
之所以能夠不用執(zhí)行方法直接拿到緩存結(jié)果,是因為將執(zhí)行結(jié)果存到了緩存中。既然有存緩存的過程,自然有刪除緩存的過程,而這個操作就要用到@CacheEvict這個注解了。
還是通過實例來看,這里舉出兩個例子——根據(jù)方法清除緩存和清除全部緩存。
我們在PersonService中分別加上這兩個接口方法
稍稍解釋下,當(dāng)updatePerson()方法被調(diào)用時,其會根據(jù)key來取出相應(yīng)的緩存記錄刪除;而對于方法reload()則是在該方法被調(diào)用時,清空所有緩存記錄。
測試代碼如下
Person lucy = personService.findPerson(1);Person lily = personService.findPerson(2);lucy.setName("Tracy");personService.updatePerson(lucy);System.out.println(personService.findPerson(1));System.out.println(personService.findPerson(2));personService.reload();System.out.println(personService.findPerson(1));System.out.println(personService.findPerson(2));執(zhí)行結(jié)果如下
real query person object info real query person object info update: Tracy real query person object info Person{id=1, age=18, name='Jackie'} Person{id=2, age=18, name='Jackie'} real query person object info Person{id=1, age=18, name='Jackie'} real query person object info Person{id=2, age=18, name='Jackie'}第1,2行分別是因為針對id=1,2都是第一次查詢,這時候沒有緩存記錄,所以都真實執(zhí)行了方法findPerson();
第3行是調(diào)用方法updatePerson()打印的信息
第4,5行是再次查詢id=1的Person信息,這里之所以打印出real query person object info是因為之前調(diào)用了id=1時的updatePerson()方法,該方法觸發(fā),根據(jù)getId()找到id=1的緩存記錄進(jìn)行刪除,所以這時候查找id=1的時候,緩存記錄已經(jīng)不存在,故而要執(zhí)行findPerson()方法。
第6行是再次查詢id=2的Person信息,因為之前已經(jīng)查過一次,并且沒有刪除過這條緩存記錄,所以再次查找時,直接用緩存結(jié)果。
第7,8行是再次查詢id=1的Person信息,注意再次之前,執(zhí)行了reload()方法,這個方法會清楚所有的緩存信息,所以對于id=1和2的緩存記錄都已經(jīng)清空,這里就又重新執(zhí)行findPerson()方法
第9,10行同7,8
當(dāng)然,關(guān)于Spring Cache還有很多靈活的應(yīng)用以及功能強(qiáng)大的注解和用法,這里只是通過實例了解Spring Cache有什么用,如何用。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續(xù)關(guān)注我的文章,請掃描二維碼,關(guān)注JackieZheng的微信公眾號,我會將我的文章推送給您,并和您一起分享我日常閱讀過的優(yōu)質(zhì)文章。
轉(zhuǎn)載于:https://www.cnblogs.com/bigdataZJ/p/SpringAction5.html
總結(jié)
以上是生活随笔為你收集整理的Spring实战——缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决jsp两种提交方式乱码 的方法
- 下一篇: 电池耐用!诺基亚新机获得FCC认证 搭载