spring3.1.0开始支持注解方式的缓存实现,非常方便,不过它目前只支持java内置的ConcurrentMap和ehcache这两种缓存方式,因为项目用到memcache,就想把memcache集成到spring内置的缓存中,使memcache也能用注解方式来调用。于是参考ehcache的集成方式,把memcache集成到项目中。spring把所有缓存都抽象为一个cache,相当于一个缓存集合,即spring缓存注解@Cacheable(value="xxx")中xxx对应的结果集合。首先我们要实现Cache这个接口,memcache的java客户端我们用的是com.danga.MemCached.MemCachedClient这个,代码如下:
public class MemcacheCache implements Cache { private MemCachedClient client; private String name; public MemcacheCache(){ } public MemcacheCache(String name,MemCachedClient client) { Assert.notNull(client, "Memcache client must not be null"); // TODO validate memcache "alive" this.client = client; this.name = name; } @Override @Cacheable(value="xxxx") public String getName() { return this.name; } @Override public Object getNativeCache() { return this.client; } @Override public ValueWrapper get(Object key) { Object value = this.client.get(objectToString(key)); return (value != null ? new SimpleValueWrapper(value) : null); } @Override public void put(Object key, Object value) { this.client.set(objectToString(key), value); } @Override public void evict(Object key) { this.client.delete(objectToString(key)); } @Override public void clear() { // TODO delete all data } private static String objectToString(Object object) { if (object == null) { return null; } else if (object instanceof String) { return (String) object; } else { return object.toString(); } } public void setClient(MemCachedClient client){ this.client = client; } public MemCachedClient getClient() { return client; } public void setName(String name) { this.name = name; } }
然后是要扩展AbstractCacheManager这个缓存管理抽象类,它主要负责生成和读取Cache,代码如下:
public class MemcacheCacheManager extends AbstractCacheManager { private Collection<Cache> caches; private MemCachedClient client = null; public MemcacheCacheManager() { } public MemcacheCacheManager(MemCachedClient client){ setClient(client); } @Override protected Collection<? extends Cache> loadCaches() { return this.caches; } public void setCaches(Collection<Cache> caches) { this.caches = caches; } public void setClient(MemCachedClient client) { this.client = client; updateCaches(); } public Cache getCache(String name){ checkState(); Cache cache = super.getCache(name); if(cache == null){ cache = new MemcacheCache(name, client); addCache(cache); } return cache; } private void checkState() { if(client == null){ throw new IllegalStateException("MemcacheClient must not be null."); } //TODO check memcache state } private void updateCaches() { if(caches != null){ for(Cache cache : caches){ if(cache instanceof MemcacheCache){ MemcacheCache memcacheCache = (MemcacheCache)cache; memcacheCache.setClient(client); } } } } }
配置bean:
<bean id="cacheManager" class="com.youboy.cshop.utils.memcache.MemcacheCacheManager"> <property name="client" value="memcachedClient"/> <property name="caches"> <set> <bean class="com.youboy.cshop.utils.memcache.MemcacheCache"> <property name="name" value="testCache"/> <property name="client" ref="memcachedClient"/> </bean> </set> </property> </bean>
其中memcachedClient为你memcache的客户端,你可以配置多个MemcacheCache,配置完这里你就你就可以把@Cacheable(value="testCache")添加到方法那来缓存执行结果,这里value="testCache"的值必须和上面bean文件配置的一致,否则无法缓存。这只是做了个简单的集成,还有很多要完善的,比如连接时检查memcache状态。