package cn.org.rapid_framework.cache.aop.interceptor;
import java.util.Iterator;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import cn.org.rapid_framework.cache.Cache;
import cn.org.rapid_framework.cache.aop.annotation.MethodCache;
import edu.emory.mathcs.backport.java.util.Arrays;
/**
* 方法缓存的拦截器,拦截有MethodCache标注的方法,并缓存结果.
*
* @author badqiu
*
*/
public class AnnotationMethodCacheInterceptor implements MethodInterceptor,BeanFactoryAware,InitializingBean {
private Cache methodCache;
private BeanFactory beanFactory;
private String methodCacheBeanName = null;
private String cacheKeyPrefix = "";
public void setMethodCache(Cache methodCache) {
this.methodCache = methodCache;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
if (invocation.getMethod().isAnnotationPresent(MethodCache.class)) {
String targetName = invocation.getThis().getClass().getName();
String methodName = invocation.getMethod().getName();
Object[] arguments = invocation.getArguments();
MethodCache annotation = invocation.getMethod().getAnnotation(MethodCache.class);
String cacheKey = getCackeKey(targetName, methodName, arguments,annotation);
int expireSeconds = (int)annotation.expireTime();
return getResult(cacheKey, invocation,expireSeconds);
} else {
return invocation.proceed();
}
}
private Object getResult(String cacheKey,MethodInvocation invocation, int expireSeconds) throws Throwable {
Object result = methodCache.get(cacheKey);
if(result == null) {
result = invocation.proceed();
methodCache.set(cacheKey, result, expireSeconds);
}
return result;
}
protected String getCackeKey(String className, String methodName,Object[] arguments, MethodCache annotation) {
String cacheKey = null;
if(StringUtils.isEmpty(annotation.cacheKey())) {
cacheKey = createDefaultCacheKey(className, methodName, arguments);
}else {
cacheKey = createCacheKey(annotation.cacheKey(),arguments);
}
return cacheKeyPrefix + cacheKey;
}
protected String createCacheKey(String cacheKey, Object[] args) {
String result = cacheKey;
if(cacheKey.indexOf("{args}") >= 0) {
result = StringUtils.replace(result, "{args}", ""+StringUtils.join(args,','));
}
return String.format(result, args);
}
protected String createDefaultCacheKey(String className, String methodName,Object[] arguments) {
StringBuilder datakey = new StringBuilder();
datakey.append(className).append(".").append(methodName).append("(");
if(arguments != null) {
for(int i = 0; i < arguments.length; i++) {
Object arg = arguments[i];
datakey.append(objectToString(arg));
if(i != arguments.length - 1) {
datakey.append(",");
}
}
}
datakey.append(")");
return datakey.toString();
}
private String objectToString(Object arg) {
String argString = null;
if(arg == null) {
argString = "";
}else if(arg.getClass().isArray()) {
argString = "["+StringUtils.join(((Object[])arg), ',')+"]";
}else if(arg instanceof Iterable) {
argString = "["+StringUtils.join(((Iterable)arg).iterator(), ',')+"]";
}else {
argString = arg.toString();
}
return argString;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void setMethodCacheBeanName(String methodCacheBeanName) {
this.methodCacheBeanName = methodCacheBeanName;
}
public String getCacheKeyPrefix() {
return cacheKeyPrefix;
}
/**
* cacheKey的前缀,增加在所有的cacheKey中,主要用于不同系统间的cache划用,
* @param cacheKeyPrefix
*/
public void setCacheKeyPrefix(String cacheKeyPrefix) {
this.cacheKeyPrefix = cacheKeyPrefix == null ? "" : cacheKeyPrefix;
}
public void afterPropertiesSet() throws Exception {
if(methodCache == null) {
methodCache = (Cache)beanFactory.getBean(methodCacheBeanName);
}
Assert.notNull(methodCache,"'methodCache' must be not null");
}
}