###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...张三 去数据库查询