缓存方法 : Srping+Ehcache 在Service层配置缓存 [url]http://panyongzheng.iteye.com/blog/2234167[/url]
AOP面向切入实现service层嵌入缓存
//放入缓存注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface Cacheable { //放入
String key(); //缓存key
String fieldKey();// field值
int expireTime() default 3600;
}
//从缓存中销毁注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheEvict { //销毁
String key();
String[] fieldKey();
int expireTime() default 3600;
}
Aspect类
//环绕切入
@Around(value = "@annotation(com.xx.cache.annotation.Cacheable)")
public Object cache(ProceedingJoinPoint pjp) {
Object result = null;
Method method = getMethod(pjp);
Cacheable cacheable = method.getAnnotation(Cacheable.class);
String fieldKey = cacheable.fieldKey();
if (cacheable.fieldKey().indexOf("#") == 0) {//动态变量存入方式
fieldKey = parseKey(cacheable.fieldKey(), method, pjp.getArgs());
}
if (useCache) {//判断是否开启缓存 开启缓存 从缓存获取 result
//获取方法的返回类型,让缓存可以返回正确的类型
Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType();
//使用redis 的hash进行存取,易于管理
// result = JedisUtils.hget(cacheable.key(), fieldKey,method.getReturnType());
result = JedisUtils.hget(cacheable.key(), fieldKey, returnType);
if (result == null) {
try {
result = pjp.proceed();
// Assert.notNull(fieldKey);
JedisUtils.hset(cacheable.key(), fieldKey, result);
logger.debug("The " + cacheable.key() + " add to redis, the fieldKey is " + fieldKey);
} catch (Throwable e) {
e.printStackTrace();
}
}
return result;
}
try {
return pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
//环绕切入
@Around(value = "@annotation(com.xx.cache.annotation.CacheEvict)")
public Object evict(ProceedingJoinPoint pjp) {
//和cache类似,使用Jedis.hdel()删除缓存即可
if (useCache) {//判断是否开启缓存
Method method = getMethod(pjp);
CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class);
String[] fieldKeys = cacheEvict.fieldKey();
int deleteSuccessFlag = 0;
for (String fieldKey : fieldKeys) {
if (fieldKey.indexOf("#") == 0) {//动态变量存入方式
String t = fieldKey;
fieldKey = parseKey(fieldKey, method, pjp.getArgs());
if (fieldKey == null) {
logger.error("cache evict fieldkey {} connot be null, that may be cause data connot sync ", t);
t = null;
}
}
deleteSuccessFlag += JedisUtils.hdel(cacheEvict.key(), fieldKey == null ? "" : fieldKey);
logger.debug("The reference fieldkey: " + fieldKey + " for " + cacheEvict.key() + " has been delete from redis");
}
logger.debug("Delete " + deleteSuccessFlag + " " + cacheEvict.key() + "from redis");
}
try {
return pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
/**
* 获取缓存的key
* key 定义在注解上,支持SPEL表达式
*
* @param key
* @param method
* @param args
* @return
*/
private String parseKey(String key, Method method, Object[] args) {
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
return parser.parseExpression(key).getValue(context, String.class);
}
使用,在service调用前使用:
@Cacheable(key = "biz_member",fieldKey = "#id")
public Member get(String id) {
return super.get(id);
}
@CacheEvict(key = "member",fieldKey = {"#member.id","#member.account"})
public Serializable save(Member member) {
return dao.insert(member);
}
@CacheEvict(key = "member",fieldKey = {"#member.id","#member.account"})
public void delete(Member member) {
dao.delete(member);
}