AOP面向切入实现service层嵌入缓存
博客专区 > vill_520 的博客 > 博客详情
AOP面向切入实现service层嵌入缓存
vill_520 发表于2年前
AOP面向切入实现service层嵌入缓存
  • 发表于 2年前
  • 阅读 545
  • 收藏 32
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

摘要: 通过注解,使用redis,将数据库中的数据放入缓存,便于下次使用,避免直接访问数据库
//放入缓存注解

@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);
}



转载请声明。



共有 人打赏支持
粉丝 3
博文 5
码字总数 2584
×
vill_520
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: