`
tom_seed
  • 浏览: 318411 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring使用注解式@Cache集成xmemcache

 
阅读更多

在《Spring集成memcache(二)xmemcache》的基础之上扩展支持注解形式,使开发更加简洁。

参考资料如下:

http://zj0121.iteye.com/blog/1852270

 

需要注意的是扩展支持注解需要Spring AOP的支持,需要导入相应的jar包:

1.aopalliance-1.0.jar

2.aopalliance-alpha1.jar

3.slf4j-api-1.7.5.jar

其中slf4j-api-1.7.5.jar提供的是日志的接口规范,如果工程目录下使用的是log4j,则slf4j-api-1.7.5.jar会绑定调用log4j.jar。

具体说明可以访问http://blog.csdn.net/tengdazhang770960436/article/details/18006127

 

从头开始进行配置,步骤如下:

1.添加xmemcache.jar包至工程中;

  • aopalliance-1.0.jar
  • aopalliance-alpha1.jar
  • slf4j-api-1.7.5.jar
  • xmemcached-1.3.8.jar

2.在web.xml文件中添加配置

 

<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>  
        /WEB-INF/conf/spring/*-beans.xml  
    </param-value>  
</context-param>

 

 

3.在属性文件中添加如下配置:

 

#memcache配置  
memcache.ip=127.0.0.1  
memcache.port=11211  
memcache.pool.size=5  

 

 

4.在/WEB-INF/conf/spring/目录下添加配置文件memcache-beans.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="  
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
        http://www.springframework.org/schema/cache  
        http://www.springframework.org/schema/cache/spring-cache-3.2.xsd"
	default-autowire="byName">

	<bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
		<constructor-arg>
			<list>
				<bean class="java.net.InetSocketAddress">
					<constructor-arg value="${memcache.ip}" />
					<constructor-arg value="${memcache.port}" />
				</bean>
			</list>
		</constructor-arg>
		<property name="connectionPoolSize" value="${memcache.pool.size}" />
		<property name="commandFactory">
			<bean class="net.rubyeye.xmemcached.command.BinaryCommandFactory" />
		</property>
		<property name="transcoder">
			<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
		</property>
	</bean>

	<bean id="memcachedClient" factory-bean="memcachedClientBuilder"
		factory-method="build" destroy-method="shutdown" />
		
	<bean id="cacheManager" class="com.iaccount.framework.cache.memcache.MemcachedCacheManager">
		<property name="memcachedClient" ref="memcachedClient" />
		<property name="configMap">
			<map>
				<!-- key:@Cacheable、@CachePut、@CacheEvict等的value属性。value:缓存过期时间(单位:秒),默认值:0 -->
				<entry key="defaultCache" value="0" /><!-- 默认缓存区 不过期 -->
				<entry key="inTimeCache" value="3600" /><!-- 实时缓存区 一小时过期 -->
			</map>
		</property>
	</bean>

	<cache:annotation-driven cache-manager="cacheManager" />
</beans>

 

 

5.参考了EHCacheCacheManager的源码,写了一个基于XMemcached的MemcachedCacheManager

a.memcache缓存连接类 MemCache.java  

 

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeoutException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;
	}
}

 

 

b.缓存类  MemcachedCache.java  

 

import net.rubyeye.xmemcached.MemcachedClient;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

public class MemcachedCache implements Cache{
	private final String name;
	private final MemcachedClient memcachedClient;
	private final MemCache memCache;
	
	public MemcachedCache(String name, int expire, MemcachedClient memcachedClient){
		this.name = name;
		this.memcachedClient = memcachedClient; 
		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 MemcachedClient getNativeCache(){
		return this.memcachedClient;
	}

	@Override
	public void put(Object key, Object value){
		memCache.put(key.toString(), value);
	}
}

 

 

c.缓存管理类  MemcachedCacheManager.java

 

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import net.rubyeye.xmemcached.MemcachedClient;

import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;

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;

	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;
	}
}

 

 

6.数据操作类

 

@Cacheable(value="defaultCache")
public List<FmSupplier> getEnableSuppliers(){
	FmSupplierQuery query = new FmSupplierQuery();
	query.setIsDeleted(YesNoType.NO.getCode());
	query.setSupplierStatus(SupplierStatus.ENABLE.getCode());
	return fmSupplierMapper.selectListByQuery(query);
}

@Cacheable(value="defaultCache", key="#id")
public FmSupplier selectByPrimaryKey(Long id){
	return fmSupplierMapper.selectByPrimaryKey(id);
}

 

 

1.在缓存区defaultCache中获取数据,第一次请求时无数据,则会从数据库中获取并放至缓存中;

2.第二次请求时则直接从缓存中获取;

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics