Spring實戰 快取

2021-09-08 04:28:25 字數 3991 閱讀 8024

提到快取,你能想到什麼?一級快取,二級快取,web快取,redis……

你所能想到的各種包羅永珍存在的打著快取旗號存在的各種技術或者實現,無非都是宣揚快取技術的優勢就是快,無需反覆查詢等。

當然,這裡要講的不是一級二級,也不是redis,而是spring的快取支援。當時基於工作上的業務場景,考慮需要用到快取技術,但是並不清楚該用什麼樣的快取技術,起初甚至有想過把資訊寫到redis中,然後讀redis的資訊(現在想想,真是小題大做),後來發現spring提供了快取的解決方案——spring cache。雖然最終找到了乙個更加簡便討巧的方式解決了問題,但是今天還是把自己零碎的spring cache知識稍稍梳理下。

這裡大概介紹下業務場景:

流程圖如下:

有關spring cache的理論詳細介紹可以看官方文件或者參閱《spring實戰》第十三章,這裡偏**實戰看看spring cache如何使用。

就像如果要啟用aop需要新增

一樣,如果要用cache,也需要宣告

這樣還不夠,除此以外,我們還需要乙個快取管理器

這個快取管理器是spring快取抽象的核心,可以繼承多個流行的快取實現。從上面的宣告可以看出,這裡宣告了concurrentmapcachemanager管理器,從字面就可以看出其內容實現應該是通過concurrenthashmap來做快取的。(除了這個簡單的快取管理器,當然還有如noopcachemanager、ehcachecachemanager、rediscachemanager、compositecachemanager等管理器)

這裡的personcache就是本例中用到的宣告的管理器

以上的xml宣告可以存放到乙個spring-cache.xml中,完整內容如下

@component

public class person

public void setid(int id)

public int getage()

public void setage(int age)

public string getname()

public void setname(string name)

@override

public string tostring() ';}}

@service("personservice")

public class personservice

}

findperson()方法很簡單,主要是根據id查詢到相應的person物件。

這裡第一行加上了列印資訊,用於區分每次呼叫是否走快取了。如果直接用的是快取結果,則不會列印這句話,如果沒有快取,則需要執行函式體,從而列印改行顯示。

@cacheable註解:主要用來配置方法,能夠根據方法的請求引數對其結果進行快取。即當重複使用相同引數呼叫方法的時候,方法本身不會被呼叫執行,即方法本身被略過了,取而代之的是方法的結果直接從快取中找到並返回了。簡而言之就是如果快取有則取出,如果沒有則執行方法。

到此我們就可以驗證了。編寫**如下

public class springcache 

}

最終執行結果如下

real query person object info

person

person

可以看出第一次結果顯示前列印出了real query person object info說明真實執行了findperson()方法;

第二次列印的結果沒有包含這行資訊,說明是從快取中直接取的資料,而且通過除錯打斷點確實發現第二次並未進入findperson()方法。

之所以能夠不用執行方法直接拿到快取結果,是因為將執行結果存到了快取中。既然有存快取的過程,自然有刪除快取的過程,而這個操作就要用到@cacheevict這個註解了。

還是通過例項來看,這裡舉出兩個例子——根據方法清除快取和清除全部快取。

我們在personservice中分別加上這兩個介面方法

@cacheevict(value = "personcache", key = "#person.getid()")

public void updateperson(person person)

@cacheevict(value = "personcache", allentries = true)

public void reload()

稍稍解釋下,當updateperson()方法被呼叫時,其會根據key來取出相應的快取記錄刪除;而對於方法reload()則是在該方法被呼叫時,清空所有快取記錄。

測試**如下

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));

執行結果如下

real query person object info

real query person object info

update: tracy

real query person object info

person

person

real query person object info

person

real query person object info

person

第1,2行分別是因為針對id=1,2都是第一次查詢,這時候沒有快取記錄,所以都真實執行了方法findperson()

第3行是呼叫方法updateperson()列印的資訊

第4,5行是再次查詢id=1的person資訊,這裡之所以列印出real query person object info是因為之前呼叫了id=1時的updateperson()方法,該方法觸發,根據getid()找到id=1的快取記錄進行刪除,所以這時候查詢id=1的時候,快取記錄已經不存在,故而要執行findperson()方法。

第6行是再次查詢id=2的person資訊,因為之前已經查過一次,並且沒有刪除過這條快取記錄,所以再次查詢時,直接用快取結果。

第7,8行是再次查詢id=1的person資訊,注意再次之前,執行了reload()方法,這個方法會清楚所有的快取資訊,所以對於id=1和2的快取記錄都已經清空,這裡就又重新執行findperson()方法

第9,10行同7,8

Spring實戰 清除快取

一 配置檔案 二 屬性檔案 三 領域模型 public class user public user string name,int age public string getname public void setname string name public int getage public ...

Spring實戰 快取使用condition

一 配置檔案 二 屬性檔案 三 領域模型 public class user public user string name,int age public string getname public void setname string name public int getage public ...

Spring註解快取設計原理及實戰

spring 3.1後引入註解快取,其本質不是乙個具體的快取實現,而是乙個對快取使用的抽象。通過在既有 中新增少量自定義註解,即可夠達到使用快取物件和快取方法的返回物件的效果。spring的快取技術具備相當的靈活性,不僅能夠使用spel來定義快取的key和各種condition,還提供開箱即用的快取...