AOP面向切入实现service层嵌入缓存

缓存方法 : Srping+Ehcache 在Service层配置缓存 http://panyongzheng.iteye.com/blog/2234167
AOP面向切入实现service层嵌入缓存 http://my.oschina.net/vill/blog/550715
//放入缓存注解
 
@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);
}





转载请声明。

你可能感兴趣的:(AOP面向切入实现service层嵌入缓存)