###1、spring提供以下註解來支持spring cache
####1.@Cacheable
使用@Cacheable標記的方法,在執行該方法時,spring先去緩存中查詢一次,若是查詢到結果,直接返回結果(即該方法實際不會被執行);不然,執行該方法,將結果緩存。
@Cacheable能夠標記在一個方法(表示該方法支持緩存)或標記在一個類上(該類的全部方法均支持緩存)
須要注意的是:支持緩存的方法在對象內部被調用時是不會觸發緩存功能的
@Cacheable指定屬性有:
value 緩存空間名稱
key 緩存的key,根據這個key去上述緩存空間中查詢對象值
condition 緩存的條件,能夠爲空。可使用spel編寫返回true或false,只有true時才進行緩存 ####2.@CachePut
使用@CachePut標記的方法,在執行該方法時,每次都執行實際方法,將結果緩存。
####3.@CacheEvict
使用@CacheEvict標記的方法,會在方法執行以前或以後移除springCache中某些元素
@CacheEvict指定的屬性有:
value:緩存空間名稱
key:緩存的key
condition:緩存條件
allEntries:是否清空全部緩存內容,缺省值爲false,若是指定true,則方法調用後當即清除全部的緩存
beforeInvocation:是否在執行方法以前就清空全部的緩存,缺省值false,若是指定true,則方法尚未執行前就清空緩存;缺省狀況下,若是方法拋出異常,則不會清空緩存
####4.@Caching
它可讓咱們在一個方法或類上同時指定多個spring cache相關注解java
###2、實際例子
基於上一篇《純java實現緩存》,咱們這裏從新定義業務類(MyAccountService)和測試類(Main),自定義的緩存管理器類不須要了,由於spring已經爲咱們提供了。
從新定義服務類以下spring
package com.test.spring.cacheCommon; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; /** * 業務類 */ public class MyAccountService { /** * 該註解的意思是:當調用getAccountByName這個方法時,spring會從一個名叫accountCache的緩存空間中查詢 * 注意:1.這裏沒有指定查詢的key,因此spting默認傳參name做爲key,value爲Account對象。 * 2.accountCache這個名稱須要在spring的xml文件中配置 * 若是查詢到了,則直接返回結果,不執行getAccountByName方法 * 不然,執行getAccountByName方法,並將查詢結果緩存起來 */ @Cacheable(value="accountCache") //根據key獲取對象值 public Account getAccountByName(String name){ Account result = getFromDB(name); return result; } /** * 清除這個key值(account.getName())的對象值 */ @CacheEvict(value="accountCache",key="#account.getName()") public void updateAccount(Account account){ updateFromDB(account); } //數據庫查詢帳號信息 private Account getFromDB(String name) { System.out.println("去數據庫查詢"); return new Account(name); } //更新帳號信息 private void updateFromDB(Account account){ System.out.println("更新帳號信息"+account.getName()); } }
測試類以下數據庫
package com.test.spring.cacheCommon; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 測試類 * */ public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml"); MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService"); //第一次查詢,去數據庫查詢 myAccountService.getAccountByName("張三"); //第二次查詢,從緩存中查詢 myAccountService.getAccountByName("張三"); //清空緩存 Account account1 = myAccountService.getAccountByName("張三"); myAccountService.updateAccount(account1); //第三次查詢,從數據庫查詢 myAccountService.getAccountByName("張三"); //第四次查詢,從緩存中查詢 myAccountService.getAccountByName("張三"); } }
xml文件配置以下緩存
<!-- 服務bean配置 --> <bean id="myAccountService" class="com.test.spring.cacheCommon.MyAccountService"></bean> <!-- 配置緩存管理器 1.它有一個屬性caches,即這個管理器全部的空間名稱的集合 2.若是方法上缺省空間名稱,則默認爲default 3.咱們還定義了一個名字叫作 accountCache 4.使用了缺省的內存方案ConcurrentMapCacheFactoryBean,它是基於java.util.concurrent.ConcurrentHashMap的一個內存緩存實現方法 --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"></bean> <!-- 指定spring緩存空間名稱 --> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="accountCache"></bean> </set> </property> </bean> <!-- 啓用緩存註解 --> <cache:annotation-driven cache-manager="cacheManager"/>
輸出結果測試
去數據庫查詢 更新帳號信息張三 去數據庫查詢
###多個參數時,如何制定key
1.修改基礎bean日誌
public class Account { private int id; private String name; //新增字段 private String password; }
2.業務類code
public class MyAccountService { /** * 注意 key的組合 */ @Cacheable(value="accountCache",key="#name.concat(#password)") //根據key獲取對象值 public Account getAccountByName(String name,String password){ Account result = getFromDB(name,password); return result; } //數據庫查詢帳號信息 private Account getFromDB(String name,String password) { System.out.println("去數據庫查詢"); return new Account(name,password); } }
3.測試方法xml
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml"); MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService"); //第一次查詢,去數據庫查詢 myAccountService.getAccountByName("張三","123456"); //第二次查詢,從緩存中查詢 myAccountService.getAccountByName("張三","123456"); //第三次查詢,從數據庫查詢 myAccountService.getAccountByName("張三","654321"); //第四次查詢,從緩存中查詢 myAccountService.getAccountByName("張三","654321"); } }
###@CachePut註解使用
實際的工程中,存在這種狀況,咱們但願某一個方法每次執行都必須被調用,由於這個方法不單單隻返回結果,還作了其它的事情,好比:記錄日誌等。所以這個時候要使用@CachePut註解,它能保證該方法必定被執行,同時返回值被記錄到緩存中。
業務類對象
package com.test.spring.cacheCommon; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; /** * 業務類 */ public class MyAccountService { /** * key的組合使用 */ @Cacheable(value="accountCache",key="#name.concat(#password)") //根據key獲取對象值 public Account getAccountByName(String name,String password){ Account result = getFromDB(name,password); return result; } /** * * @CachePut使用 * */ @CachePut(value="accountCache",key="#account.getName()") public Account updateAccount(Account account) { return updateDB(account); } //更新帳號信息 private Account updateDB(Account account) { System.out.println("real updating db..."+account.getName()); return account; } //數據庫查詢帳號信息 private Account getFromDB(String name,String password) { System.out.println("去數據庫查詢"); return new Account(name,password); } }
測試類內存
package com.test.spring.cacheCommon; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 測試類 * */ public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml"); MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService"); //第一次查詢,去數據庫查詢 myAccountService.getAccountByName("張三","123456"); //第二次查詢,從緩存中查詢 myAccountService.getAccountByName("張三","123456"); // Account account = myAccountService.getAccountByName("張三", "123456"); myAccountService.updateAccount(account); //第三次查詢,從數據庫查詢 myAccountService.getAccountByName("張三","123456"); //第四次查詢,從數據庫查詢 myAccountService.getAccountByName("張三","654321"); //第五次查詢,從緩存中查詢 myAccountService.getAccountByName("張三","654321"); } }
輸出結果
去數據庫查詢 real updating db...張三 去數據庫查詢