程序员人生 网站导航

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

栏目:框架设计时间:2015-02-06 08:24:25

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

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

1、首先我们得定义1个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有很多不同得客户端,那末我会定义1个自己的接口。让用户自行实现。下面就是接口,定义了1些简单的方法

package org.xiezhaodong.spring.cache.cacheutil; /** * 2015⑴⑴4 * @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代理1定要开启

<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")//表示要缓存id public Object testaop(String id) { return "sssss"; }


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


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


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐