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狀態。