spring--springCache原理和擴展性

###1.springcache原理 springCache的關鍵原理就是spring aop,經過sop的前置通知/後置通知/返回通知,實現了方法在調用前、調用後獲取方法的入參和返回值,進而實現了緩存的邏輯。
原理理解:客戶端調用spring中的方法時(假設方法名爲A),spring cache利用spring aop動態代理技術,給客戶端的不是方法A,而是一個動態生成的類。這個時候客戶端在調用方法A的時候,實際上調用的是動態類生成的方法(假設B),這個時候動態類能夠總體的控制實際方法A的入參和返回值,即將其結果緩存起來等。
###2.springcache擴展性
springcache不支持高併發可用性,也不具有持久化數據能力(所以,我引入了spring集成redis這篇文章),這個時候,咱們就須要自定義緩存方案。
1.咱們須要提供一個CacheManager接口的實現。這個接口會告訴spring有哪些cache實例,spring會根據cache的名字查找cache的實例。
2.實現Cache接口,cache接口負責實際的緩存邏輯,例如增長對象/更新對象、刪除對象等。
3.利用Cache接口,咱們能夠快速的對接第三方緩存系統
####基礎類java

/**
 * 基本類
 */
public class Account {
	private int id;
	private String name;
	private String password;
}

####業務類redis

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

####MyCachespring

package com.test.spring.cacheCommon;

import java.util.HashMap;
import java.util.Map;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

public class MyCache implements Cache{
	
	//自定義私有參數
	private String name;

	private Map<String, Object> store = new HashMap<String, Object>();
	
	//無參構造器
	public MyCache() {
		
	}
	
	//有參構造器
	public MyCache(String name) {
		this.name = name;
	}
	
	@Override
	public String getName() {
		return name;
	}

	@Override
	public Object getNativeCache() {
		return store;
	}

	@Override
	public ValueWrapper get(Object key) {
		
	     ValueWrapper result = null; 
	     Object thevalue = store.get(key); 
	     if(thevalue!=null) { 
	       result = new SimpleValueWrapper(thevalue); 
	     } 
		
		return result;
	}

	@Override
	public <T> T get(Object key, Class<T> type) {
		return type.cast(store.get(key));
	}

	@Override
	public void put(Object key, Object value) {
		store.put((String)key, value);
	}

	@Override
	public ValueWrapper putIfAbsent(Object key, Object value) {
        put(key, value);  
        return new SimpleValueWrapper(value); 
	}

	@Override
	public void evict(Object key) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clear() {
		store.clear();
	}

	public void setName(String name) {
		this.name = name;
	}	

}

####緩存管理器類數據庫

package com.test.spring.cacheCommon;

import java.util.Collection;

import org.springframework.cache.support.AbstractCacheManager;

/**
 * 該類繼承了spring的AbstractCacheManager
 * 僅僅管理MyCache
 *
 */
public class MyCacheManager extends AbstractCacheManager{

	private Collection<? extends MyCache> caches;
	
	@Override
	protected Collection<? extends MyCache> loadCaches() {
		// TODO Auto-generated method stub
		return this.caches;
	}


	public void setCaches(Collection<? extends MyCache> caches) {
		this.caches = caches;
	}
	

}

####測試類緩存

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...張三
去數據庫查詢
相關文章
相關標籤/搜索