Spring Aop 實現一個簡單的memcached小插件
來源:程序員人生 發布時間:2015-02-06 08:24:25 閱讀次數:3462次
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
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈