spring 从3.x就提供了cache接口,spring默认实现的缓存是ehcache,spring的cache接口:
- public interface Cache {
- String getName();
- Object getNativeCache();
- ValueWrapper get(Object key);
- <T> T get(Object key, Class<T> type);
- void put(Object key, Object value);
- void evict(Object key);
- void clear();
- interface ValueWrapper {
- Object get();
- }
- }
从spring的cache接口,我们可以看出spring的cache模型就是在内存中画一片内存区域出来,为这盘内存指定名称,在这盘内存区域中以key-value的方式存放数据,画个图来说明cache的存取方式,用户和部门的缓存,名称分别为DepartCache和UserCache
1. 要使用spring的cache,首先要实现cacheManager, 可以参考spring对ehcache的实现,整合memcached的代码如下:
- /**
- * Spring Cache整合Memcached实现
- * @author liuyazhuang
- */
- public class MemcachedCacheManager extends AbstractTransactionSupportingCacheManager {
- private ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>();
- private Map<String, Integer> expireMap = new HashMap<String, Integer>(); //缓存的时间
- private MemcachedClient memcachedClient; //xmemcached的客户端
- public MemcachedCacheManager() {
- }
- @Override
- protected Collection<? extends Cache> loadCaches() {
- Collection<Cache> values = cacheMap.values();
- return values;
- }
- @Override
- public Cache getCache(String name) {
- Cache cache = cacheMap.get(name);
- if (cache == null) {
- Integer expire = expireMap.get(name);
- if (expire == null) {
- expire = 0;
- expireMap.put(name, expire);
- }
- cache = new MemcachedCache(name, expire.intValue(), memcachedClient);
- cacheMap.put(name, cache);
- }
- return cache;
- }
- public void setMemcachedClient(MemcachedClient memcachedClient) {
- this.memcachedClient = memcachedClient;
- }
- public void setConfigMap(Map<String, Integer> configMap) {
- this.expireMap = configMap;
- }
- }
2. 接着看下MemcachedCache的实现,主要实现spring的cache接口
- public class MemcachedCache implements Cache {
- private final String name;
- private final MemCache memCache;
- public MemcachedCache(String name, int expire, MemcachedClient memcachedClient) {
- this.name = name;
- this.memCache = new MemCache(name, expire, memcachedClient);
- }
- @Override
- public void clear() {
- memCache.clear();
- }
- @Override
- public void evict(Object key) {
- memCache.delete(key.toString());
- }
- @Override
- public ValueWrapper get(Object key) {
- ValueWrapper wrapper = null;
- Object value = memCache.get(key.toString());
- if (value != null) {
- wrapper = new SimpleValueWrapper(value);
- }
- return wrapper;
- }
- @Override
- public String getName() {
- return this.name;
- }
- @Override
- public MemCache getNativeCache() {
- return this.memCache;
- }
- @Override
- public void put(Object key, Object value) {
- memCache.put(key.toString(), value);
- }
- @Override
- @SuppressWarnings("unchecked")
- public <T> T get(Object key, Class<T> type) {
- Object cacheValue = this.memCache.get(key.toString());
- Object value = (cacheValue != null ? cacheValue : null);
- if (type != null && !type.isInstance(value)) {
- throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
- }
- return (T) value;
- }
- }
3. spring提供的这套缓存api其实就是底层缓存框架与应用程序之间的中间层转换, 这里还有一个类就是MemCache,这个类主要是对应memcached缓存的模型,spring的缓存只是提供了一套api,具体的实现要根据底层使用的什么缓存框架:
MemCache.Java
- public class MemCache {
- private static Logger log = LoggerFactory.getLogger(MemCache.class);
- private Set<String> keySet = new HashSet<String>();
- private final String name;
- private final int expire;
- private final MemcachedClient memcachedClient;
- public MemCache(String name, int expire, MemcachedClient memcachedClient) {
- this.name = name;
- this.expire = expire;
- this.memcachedClient = memcachedClient;
- }
- public Object get(String key) {
- Object value = null;
- try {
- key = this.getKey(key);
- value = memcachedClient.get(key);
- } catch (TimeoutException e) {
- log.warn("获取 Memcached 缓存超时", e);
- } catch (InterruptedException e) {
- log.warn("获取 Memcached 缓存被中断", e);
- } catch (MemcachedException e) {
- log.warn("获取 Memcached 缓存错误", e);
- }
- return value;
- }
- public void put(String key, Object value) {
- if (value == null)
- return;
- try {
- key = this.getKey(key);
- memcachedClient.setWithNoReply(key, expire, value);
- keySet.add(key);
- } catch (InterruptedException e) {
- log.warn("更新 Memcached 缓存被中断", e);
- } catch (MemcachedException e) {
- log.warn("更新 Memcached 缓存错误", e);
- }
- }
- public void clear() {
- for (String key : keySet) {
- try {
- memcachedClient.deleteWithNoReply(this.getKey(key));
- } catch (InterruptedException e) {
- log.warn("删除 Memcached 缓存被中断", e);
- } catch (MemcachedException e) {
- log.warn("删除 Memcached 缓存错误", e);
- }
- }
- }
- public void delete(String key) {
- try {
- key = this.getKey(key);
- memcachedClient.deleteWithNoReply(key);
- } catch (InterruptedException e) {
- log.warn("删除 Memcached 缓存被中断", e);
- } catch (MemcachedException e) {
- log.warn("删除 Memcached 缓存错误", e);
- }
- }
- private String getKey(String key) {
- return name + "_" + key;
- }
- }
4. 在spring的配置文件中使用MemcachedCacheManager
- <!-- 开启缓存 -->
- <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true" />
- <!-- 配置memcached的缓存服务器 -->
- <bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
- <constructor-arg>
- <list>
- <bean class="java.net.InetSocketAddress">
- <constructor-arg value="localhost" />
- <constructor-arg value="11211" />
- </bean>
- </list>
- </constructor-arg>
- </bean>
- <bean id="memcachedClient" factory-bean="memcachedClientBuilder" factory-method="build" destroy-method="shutdown" />
- <bean id="cacheManager" class="com.hqhop.framework.common.cache.memcached.MemcachedCacheManager">
- <property name="memcachedClient" ref="memcachedClient" />
- <!-- 配置缓存时间 -->
- <property name="configMap">
- <map>
- <!-- key缓存对象名称 value缓存过期时间 -->
- <entry key="typeList" value="3600" />
- </map>
- </property>
- </bean>
5. 到此为止,spring和memcached整合就完成了,spring的缓存还提供了很多的注解@Cachable,@cachePut.....,这里不多说了。