一、概述
现状:目前缓存框架底层使用redis,但是进行了统一包装,相当于对外一个新缓存框架,提供了redis基础功能
问题:缓存混乱乱,由程序员自己set,get。清理不彻底。线上出问题。
需求:项目需要使用spring cache统一对service进行缓存处理。团队统一的缓存管理,以及同外部一致的缓存策略方案
1.1、实现自定义缓存方案
参看缓存实现图:006-spring cache-缓存实现-01-SimpleCacheConfiguration、RedisCacheConfiguration
参看redis 实现架构
SpringCache本质上是一个对缓存使用的抽象,将存储的具体实现方案从缓存执行动作及流程中提取出来。缓存流程中面向的两个抽象接口是CacheManager、Cache。其中Cache提供了缓存操作的读取/写入/移除等方法,本着面向抽象编程的原则,内部将缓存对象统一封装成ValueWrapper。Cache接口代码如下:
public interface Cache { String getName(); //缓存的名字 Object getNativeCache(); //得到底层使用的缓存,如Ehcache ValueWrapper get(Object key); //根据key得到一个ValueWrapper,然后调用其get方法获取值 <T> T get(Object key, Class<T> type);//根据key,和value的类型直接获取value void put(Object key, Object value);//往缓存放数据 void evict(Object key);//从缓存中移除key对应的缓存 void clear(); //清空缓存 interface ValueWrapper { //缓存值的Wrapper Object get(); //得到真实的value } }
由于在应用中可能定义多个Cache,因此提供了CacheManager抽象,用于缓存的管理,接口代码如下:
public interface CacheManager { Cache getCache(String name); //根据Cache名字获取Cache Collection<String> getCacheNames(); //得到所有Cache的名字 }
任何实现了这两个接口的缓存方案都可以直接配置进SpringCache使用。其自带的SimpleCacheManager、ConcurrentMapCache是如此;使用ehcache作为存储实现的EhCacheCacheManager、EhCacheCache也是如此。可以自己实现CacheManager与Cache并将其集成进来。
二、自定义缓存实现
2.1、自定义缓存实现-基础版本【需要自己手动写缓存空间】
1、Cache接口,增删改差
为了方便展示,自定义缓存实现方案只实现最简单的功能,cache内部使用ConcurrentHashMap做为存储方案,使用默认实现SimpleValueWrapper,MyCache代码如下:
package com.aaa.test.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.Cache; import org.springframework.cache.support.SimpleValueWrapper; import org.springframework.context.annotation.Configuration; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @Configuration public class MyCache implements Cache { final static Logger logger = LoggerFactory.getLogger(MyCache.class); String name; Map<Object, Object> store = new ConcurrentHashMap<Object, Object>(); public MyCache() { } public MyCache(String name) { this.name = name; } @Override public String getName() { return this.name; } public void setName(String name){ this.name = name; } @Override public Object getNativeCache() { return store; } @Override public ValueWrapper get(Object key) { ValueWrapper result = null; Object thevalue = store.get(key); if(thevalue!=null) { logger.info("["+name+"]got cache, key:"+key); result = new SimpleValueWrapper(thevalue); }else{ logger.info("["+name+"]missing cache, key:"+key); } return result; } @SuppressWarnings("unchecked") @Override public <T> T get(Object key, Class<T> type) { ValueWrapper vw = get(key); if(vw==null){ return null; } return (T)vw.get(); } @SuppressWarnings("unchecked") @Override public <T> T get(Object key, Callable<T> valueLoader) { ValueWrapper vw = get(key); if(vw==null){ return null; } return (T)vw.get(); } @Override public void put(Object key, Object value) { store.put(key, value); } @Override public Cache.ValueWrapper putIfAbsent(Object key, Object value) { Object existing = this.store.putIfAbsent(key, value); return (existing != null ? new SimpleValueWrapper(existing) : null); } @Override public void evict(Object key) { store.remove(key); } @Override public void clear() { store.clear(); } }