Spring Aop 实现一个简单的memcached小插件

来源:互联网 发布:什刹海 知乎 编辑:程序博客网 时间:2024/06/09 19:55

memcached我就不多做介绍了,也就是一个分布式缓存系统!是一个典型的NOSQL。

下面我将用spring aop来实现一个简单的插件,来实现annotation方式,简单方便的取得缓存

一、首先我们得定义一个annotation.

<strong>package org.xiezhaodong.spring.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Documented@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface GetCacheVaule {public String key();//key}</strong>

因为memcached有很多不同得客户端,那么我会定义一个自己的接口。让用户自行实现。下面就是接口,定义了一些简单的方法

package org.xiezhaodong.spring.cache.cacheutil;/** * 2015-1-14 * @author xiezhaodong *缓存接口,用户自行实现 */public interface CacheSupport {long CACHE_TIME=2*60*60;//默认缓存时间为2小时/** * 加入缓存 * @param key 键 * @param value 值 * @return 是否成功 */ boolean addCache(String key,Object value);  /**  * 加入缓存,并设置缓存时间  * @param key 键  * @param value 值  * @param time 缓存时间  * @return 是否成功  */ boolean addCache(String key,Object value,long cacheTime);   /**  * 删除缓存  * @param key 键  * @return 是否成功  */ boolean deleteCache(String key);  /**  * 得到缓存  * @param key 键  * @return 返回值  */ Object getCache(String key);  /**  * 替换缓存中对应的值  * @param key 键  * @param value 值  * @return 是否替换成功  */ boolean replaceCache(String key,Object value);}

接下来就是切面了。注释里面都很详细

package org.xiezhaodong.spring.cache.aop;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.core.LocalVariableTableParameterNameDiscoverer;import org.springframework.core.ParameterNameDiscoverer;import org.xiezhaodong.spring.annotation.GetCacheVaule;import org.xiezhaodong.spring.cache.cacheutil.CacheSupport;/** * Aop切面类,实际的作用类 *  * @author xiezhaodong *  */public class GetCacheAop {private static final Log log = LogFactory.getLog(GetCacheAop.class);private CacheSupport cacheSupport;public void setCacheSupport(CacheSupport cacheSupport) {this.cacheSupport = cacheSupport;}public Object ProxyInvoke(ProceedingJoinPoint pjp) {log.info("invoke proxyinvoke method");Object result = null;// 得到运行的方法Method method = getMethod(pjp);Annotation[] annotations = method.getDeclaredAnnotations();if (annotations.length == 0) {//如果不存在注解,直接执行不缓存try {result = pjp.proceed();return result;} catch (Throwable e) {log.warn("your method " + method.getName()+ " have some errors");}}// --------------------------String cacheKey = getCacheKey(pjp, method);result = get_or_input_cache(pjp, result, cacheKey);return result;}/** * 得到缓存或者从数据库中查到并且放入缓存 * @param pjp * @param result * @param cacheKey * @return */private Object get_or_input_cache(ProceedingJoinPoint pjp, Object result,String cacheKey) {if (cacheKey != null) {result = cacheSupport.getCache(cacheKey);// 得到缓存,修改result的值if(result==null){//如果该缓存里面没有,得到result并缓存到缓存服务其中try {result=pjp.proceed();cacheSupport.addCache(cacheKey,result);return result;} catch (Throwable e) {log.warn("invoke default");}}return result;//缓存存在,直接返回result}else{//如果没有该注解直接执行方法try {result=pjp.proceed();} catch (Throwable e) {log.warn("invoke default");}}return result;}/** * 取得cache 键值 *  * @param pjp * @param method * @return 返回string */private String getCacheKey(ProceedingJoinPoint pjp, Method method) {if (method.isAnnotationPresent(GetCacheVaule.class)) {// 如果有该注解String key = method.getAnnotation(GetCacheVaule.class).key();// 得到要缓存的键值Object[] values = pjp.getArgs();// 得到顺序的参数值ParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();String[] names = discoverer.getParameterNames(method);Map<String, Integer> map = new ConcurrentHashMap<String, Integer>();for (int i = 0; i < names.length; i++) {map.put(names[i], i);// 将名字和对应的序号放入hashmap}// 得到真正的key 、value值try {Integer int_value = map.get(key);// hash中没有对应的值,表示getcachekey和名字不符合if (int_value == null) {log.warn("your cachekey is not equals" + key+ "please check this then change them");} else {String cache_key_real = (String) values[int_value];// 要缓存键值的真正cahe值return cache_key_real;}} catch (Exception e) {log.warn("your filed " + key + " must be String.class");}}return null;}/** * 得到运行时方法对象 *  * @param pjp * @return */private Method getMethod(ProceedingJoinPoint pjp) {MethodSignature methodSignature = (MethodSignature) pjp.getSignature();Method method = methodSignature.getMethod();return method;}}

然后就是xml的配置,注意cglib代理一定要开启

<bean id="aimpl" class="org.xie.service.Service_A_impl"></bean><bean id="bimpl" class="org.xie.service.Service_B_impl"></bean><bean id="memDefault" class="org.xie.framework.memcached.spring.MemcachedDefault"><property name="cached" ref="memClient"></property></bean><bean id="cacheAop" class="org.xie.framework.memcached.spring.GetCacheAop"><property name="cacheSupport" ref="memDefault"></property></bean><aop:aspectj-autoproxy proxy-target-class="true"/> <!-- cglib代理开启 --><aop:config><aop:aspect id="myAspect" ref="cacheAop"><aop:pointcut id="businessService" expression="execution(* org.xie.service.*.*(..))" /><aop:around pointcut-ref="businessService" method="ProxyInvoke" /></aop:aspect></aop:config>
那么现在service层的所有方法都有被代理了。那么我们只需要这样做,key就表示要缓存的键值

@Override@GetCacheVaule(key="id")//表示要缓存idpublic Object testaop(String id) {return "sssss";}


其实感觉也没有什么好讲的,要讲的都是在代码里面,各位都指点指点吧。但是目前只实现了醉简单的getcache,以后我会慢慢的完善各种api,敬请期待吧!!


转载请注明http://blog.csdn.net/a837199685


1 0
原创粉丝点击