文档章节

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

vill_520
 vill_520
发布于 2015/12/24 20:38
字数 546
阅读 656
收藏 32
点赞 0
评论 0
//放入缓存注解

@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

spring aop + xmemcached 配置service层缓存策略

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

bxst ⋅ 2017/07/03 ⋅ 0

使用Spring进行面向切面编程(AOP)

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

zmf ⋅ 2014/09/04 ⋅ 0

spring学习笔记-基于XML的AOP配置

AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以...

dml124 ⋅ 2012/07/30 ⋅ 0

深入了解 Dojo 的面向方面编程

简介: 面向方面的编程 “Aspect Oriented Programming,AOP” 相信大家都不陌生了。Java 中的 AspectJ 工具包对此有很好的支持。但是,在 web 开发中,似乎很少听到类似的工具。随着 Web2.0...

IBMdW ⋅ 2012/03/06 ⋅ 0

Spring的AOP原理

一、什么是 AOP AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象...

亚特兰缇斯 ⋅ 2015/03/04 ⋅ 0

AOP的基本概念

AOP框架能处理程序执行中特定切入点(Pointcut),而不与具体某个类耦合。 下面是面向切面编程的一些术语: 概念 描述 切面(Aspect) 业务流程运行的某个特定步骤,即关注点,关注点可能横切多个...

shamgod_code ⋅ 2016/10/30 ⋅ 0

spring --理解

学习完了spring,重新梳理下。 1.spring是什么?spring有哪些主要模块? spring是java企业级开源框架,它能简化javaee开发。 1.(Core Container)核心容器 beans、core、context、spel(spring...

求是科技 ⋅ 2016/09/08 ⋅ 0

Java程序员从笨鸟到菜鸟之(七十四)细谈Spring(六)spring之AOP基本概念和配置详解

首先我们来看一下官方文档所给我们的关于AOP的一些概念性词语的解释: 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的...

长平狐 ⋅ 2012/11/12 ⋅ 0

Spring学习篇:AOP知识整理

AOP知识整理 AOP(Aspect-Oriented Programming):面向切面的编程。OOP(Object-Oriented Programming)面向对象的编程。对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其...

MLGKO ⋅ 2015/11/05 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

从方法论到零售客户实践 解码阿里巴巴数据中台——2018上海云栖大会

摘要: 一、数据中台之道 6月8日,上海云栖大会进入了第二天的议程,数据中台专场论坛座无虚席,数据中台总架构师邓中华女士向在场的观众介绍了数据中台的衍生发展之道。 基于OneID、OneData...

阿里云云栖社区 ⋅ 26分钟前 ⋅ 0

Ubuntu部署django问题汇总

使用Anaconda3的Python3.6的pip安装UWSGI报错 原因是gcc版本不兼容,安装4.7并修改gccsudo apt-get install gcc-4.7sudo mv /usr/bin/gcc /usr/bin/gcc.baksudo ln -s /usr/bin/gcc-4.......

wuyaSama ⋅ 29分钟前 ⋅ 0

从方法论到零售客户实践 解码阿里巴巴数据中台——2018上海云栖大会

摘要: 一、数据中台之道 6月8日,上海云栖大会进入了第二天的议程,数据中台专场论坛座无虚席,数据中台总架构师邓中华女士向在场的观众介绍了数据中台的衍生发展之道。 基于OneID、OneData...

猫耳m ⋅ 29分钟前 ⋅ 0

Docker减肥小记

如果经常使用 docker,你会发现 docker 占用的资源膨胀很快,其中最明显也最容易被察 如何快速的清理 docker 占用的系统资源,具体点说就是删除那些无用的镜像、容器、网络和数据卷… 1、查看...

寰宇01 ⋅ 40分钟前 ⋅ 0

微信小程序中如何使用WebSocket实现长连接(含完整源码)

本文由腾讯云技术团队原创,感谢作者的分享。 1、前言 微信小程序提供了一套在微信上运行小程序的解决方案,有比较完整的框架、组件以及 API,在这个平台上面的想象空间很大。腾讯云研究了一...

JackJiang- ⋅ 48分钟前 ⋅ 0

定制库到Maven本地资源库

1.如果只有定制库的JAR文件 下载链接如下:pdf.jar 2.使用命令转换成Maven本地资源 mvn install:install-file -Dfile=/Users/manager/Downloads/clj-pdf-2.2.33.jar -DgroupId=clj-pdf -Dar......

年少爱追梦 ⋅ 52分钟前 ⋅ 0

高仿springmvc之xuchen-mvc

package org.mvc.framework.servlet; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.......

徐志 ⋅ 54分钟前 ⋅ 0

关于自定义URLStreamHandler的一次踩坑

关于自定义URLStreamHandler的一次踩坑 20180625 lambo init 说明 一般自定义实现url的协议解析.方案为实现URLStreamHandler.实现其 openConnection 就可以了, 如果我们执行 new URL("xx://...

林小宝 ⋅ 55分钟前 ⋅ 0

【SM2证书】利用BC的X509v3CertificateBuilder组装X509国密证书

演示证书文件 链接: https://pan.baidu.com/s/1ijHNnMQJj7jzW-jXEVd6Gg 密码: vfva 所需jar包 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependenc......

小帅帅丶 ⋅ 56分钟前 ⋅ 0

用Calendar 实现 计算 一段时间的毫秒值

Calendar c=Calendar.getInstance();c.add(Calendar.MONTH, -1);int lastMonthMaxDay=c.getActualMaximum(Calendar.DAY_OF_MONTH);c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH)......

岸芷汀兰 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部