###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接口,我们可以快速的对接第三方缓存系统
####基础类
/**
* 基本类
*/
public class Account {
private int id;
private String name;
private String password;
}
####业务类
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);
}
}
####MyCache
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...张三
去数据库查询