文档章节

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

vill_520
 vill_520
发布于 2015/12/24 20:38
字数 546
阅读 700
收藏 32
//放入缓存注解

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



转载请声明。



© 著作权归作者所有

共有 人打赏支持
vill_520
粉丝 3
博文 5
码字总数 2584
作品 0
武汉
技术主管
私信 提问
Android中AOP实践之一概念篇

预热 在说AOP之前先来说说java最经典的OOP(面向对象编程),我们通过面向对象的封装思想把同一类事物的共性归为一类中,方便我们统一管理。比如我们会把汽车的轮子,发动机,车身喷漆都放在...

LaxusJ
2017/11/12
0
0
spring aop + xmemcached 配置service层缓存策略

Memcached 作用与使用 基本介绍 1,对于缓存的存取方式,简言之,就是以键值对的形式将数据保存在内存中。在日常业务中涉及的操作无非就是增删改查。加入缓存机制后,查询的时候,对数据进行...

bxst
2018/06/26
0
0
大数据学习之大数据技术笔记—spring入门

篇一 spring介绍 spring.io 官网 快速开始 Aop 面向切面编程,可以任何位置,并且可以细致到方法上 连接框架与框架 Spring 就是 IOC AOP 思想 有效的组织中间层对象一般都是切入 service 层 ...

董黎明
2018/12/16
0
0
使用Spring进行面向切面编程(AOP)

转载于http://www.blogjava.net/supercrsky/articles/174368.html 文章太长,写的很好,没看完,转过来慢慢理解,品味 简介 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方...

zmf
2014/09/04
0
0
Spring Boot 使用AOP统一处理Web请求日志

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容,它通过对既有程序定义...

小致dad
2018/08/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

给windows server中的“未识别的网络”或“无法识别的网络”设置网络位置类型

在windows server中,如果网络没有被正确的识别,那么就需要手工设置一下网络位置类型。 将“公用网络”指定设置为“专用网络“ 【控制面板】--【系统和安全】--【管理工具】--【本地安全策略...

gugudu
48分钟前
1
0
阿里强制要求的21条Java开发规范,可以避免很多坑

1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。 2. 【强制】所有的覆写方法,必须加@Override注解。 说明:getObject...

天王盖地虎626
今天
7
0
oracle dg 备库未设置convert参数导致ORA-01111,ORA-01110

查看trace 文件: MRP0: Background Managed Standby Recovery process started (amls) started logmerger process Sun Jan 20 07:55:53 2019 Managed Standby Recovery starting Real Time ......

hnairdb
今天
2
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linux-tao
今天
2
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxprobe16
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部