###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...張三 去數據庫查詢