spring--springCache

###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...張三
去數據庫查詢
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息