最近遇到一个新需求:用户多次点击提交订单发生多次扣款,一开始准备配置数据库事务,但后来发现这种方法白白浪费很多资源,就改为利用接口上的切面对请求做拦截,并将当前登陆的用户存进Redis缓存,废话不说了直接上代码;

AOP的应用(模拟请求拦截器):

/**
* @author YHW
* @ClassName: ApiMemberAspect
* @Description:
* @date 2019/3/21 8:54
*/
@Aspect
@Configuration
public aspect ApiMemberAspect { private Logger logger = LoggerFactory.getLogger(getClass()); private static Gson gson = new Gson(); //切点绑在注解上方便重用!
@Pointcut("@annotation(io.renren.common.annotation.RepetitionCheck)")
public void ApiLogPointCut() { } @Before("ApiLogPointCut()")
public void beforeCheck(JoinPoint joinPoint) throws Throwable {
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++){
if("payType".equals(paramNames[i]) && paramValues[i] != null){
if(!"membercard".equals(paramValues[i])){
return;
}
}
}
for(int i = 0; i < paramNames.length; i++){
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
throw new RRException("操作超时,请等待一会后重试");
}else{
redisUtils.set(phone,phone);
}
}
}
} @After("ApiLogPointCut()")
public void afterCheck(JoinPoint joinPoint) throws Throwable{
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++){
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
redisUtils.delete(phone);
}
}
} } @AfterThrowing("ApiLogPointCut()")
public void afterException(JoinPoint joinPoint) throws Throwable{ Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++) {
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
redisUtils.delete(phone);
}
}
} } }

下面是注解类:

/**
* @author YHW
* @ClassName: RepetitionCheck
* @Description:
* @date 2019/3/21 8:58
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepetitionCheck {
String value() default "";
}

关于Redis就不多提了,自己也是处于只会用用的阶段,以后学习完会单独开一篇Redis专题;

Spring AOP初步总结(三)的更多相关文章

  1. spring AOP详解三

    CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的结束拦截所有父类方法的调用,并顺势织入横切逻辑.我们采用CGLib技术可以编写一个可以为任何类创建织入横切逻辑代理对象 ...

  2. 深入源码解析spring aop实现的三个过程

    Spring AOP的面向切面编程,是面向对象编程的一种补充,用于处理系统中分布的各个模块的横切关注点,比如说事务管理.日志.缓存等.它是使用动态代理实现的,在内存中临时为方法生成一个AOP对象,这个 ...

  3. Spring AOP实现方式三之自动扫描注入【附源码】

    注解AOP实现  这里唯一不同的就是application 里面 不需要配置每个bean都需要配置了,直接自动扫描 注册,主要知识点是怎么通过配置文件得到bean, 注意类前面的@注解. 源码结构: ...

  4. Spring AOP实现方式三【附源码】

    注解AOP实现 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.aop; /** * 谈恋爱接口 * * @author Administrator ...

  5. Spring AOP初步总结(二)

    该篇为Spring AOP的一个应用案例:系统日志 需求:将任何删除,更改或新增数据库的操作汇总到数据库中 步骤1:编写切面 @Aspect @Component public class SysLo ...

  6. Spring AOP初步总结(一)

    学习AOP有段时间了,一直没空总结一下,导致有些知识点都遗忘了,之后会把以前学过的Spring核心相关的知识点总结一轮... 先大体介绍下Spring AOP的特点(均摘自"Spring i ...

  7. Spring源码窥探之:Spring AOP初步

    AOP(Aspect Oriented Programming):即我们常说的面向切面编程. 什么是AOP?AOP是在我们原来写的代码的基础上,进行一定的包装,比如在方法执行前.方法返回后.方法抛出异 ...

  8. Spring AOP 简介(三)

    Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...

  9. Spring源码窥探之:Spring AOP初步使用

    AOP即面向切面编程.它的底层实际是用了spring的动态代理,具体是JDK的代理还是CGLIB的代理,就视情况而定了.本博客园仅仅作为平时记录,显得有些杂乱无章,如果想了解动态代理,设计模式,请访问 ...

随机推荐

  1. ParentViewController中添加SubViewController(IOS学习)

    我是用的是Container.addSubView的方法. 1. ParentViewController.m的@interface()中添加2个子vc的实例变量,代码如下 @property (no ...

  2. [转]VS 2013 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService...匹配的导出

    前几天,将Visual studio 2013 update 3 升级到了update 5.打开原来的解决方案,出现了 未找到与约束 contractname Microsoft.VisualStud ...

  3. [hdu4372]counting buildings

    解题关键: n的环排列的个数与n-1个元素的排列的个数相等. 首先可以肯定,无论从最左边还是从最右边看,最高的那个楼一定是可以看到的,从这里入手. 假设最高的楼的位置固定,最高楼的编号为n,那么我们为 ...

  4. 使用LookAndFeel为界面更换皮肤

    ----------------siwuxie095                             在 Windows 系统中,默认的 Java 运行环境(JRE)会为当前的窗体程序 指定一 ...

  5. SpringBoot04 项目热部署详解

    1 热部署 优点:适用于本地和线上.无需重启服务器 2 热部署和热加载的联系和区别 2.1 联系 不用重启服务器就可以编译和部署项目 都是基于Java的类加载器实现 2.2 字面区别 热部署在服务器运 ...

  6. 27、BLASTN的参数

    转载:http://blog.sina.com.cn/s/blog_5ecfd9d90100ksui.html http://www.docin.com/p-704735699.html 与之前的bl ...

  7. 做c语言的码农专业发展方向

    写了几年C语言代码,最近在思索,何去何从比较好? 搜索了一下,发现几个答案: 2015年10月编程语言排行榜 丢开C语言在教学应用外.在目前C语言的实际应用中.常见的应用的情景有如下: 内核/驱动,b ...

  8. sql 删除重复数据保留一条

    --创建测试表 CREATE TABLE TEST ( DEPTNO ), DNAME ), LOC ) ); --插入测试数据 , 'test1', 'test2'); , 'test1', 'te ...

  9. redis系列:redis介绍与安装

    前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...

  10. OpenStack基础知识-单元测试工具介绍

    针对以前学的内容的一个简单整理 1.单元测试工具介绍 unittest: 是 Python 的标准库,提供了最基本的单元测试功能,包括 单元测试运行器(简称runner) 和 单元测试框架.项目的单元 ...