最近遇到一个新需求:用户多次点击提交订单发生多次扣款,一开始准备配置数据库事务,但后来发现这种方法白白浪费很多资源,就改为利用接口上的切面对请求做拦截,并将当前登陆的用户存进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. C#调用ODBC连接SQL Server数据库的存储过程

    OdbcConnection con = new OdbcConnection("Driver={SQL Server};server=PC-200201070359;uid=sa;pwd= ...

  2. shell脚本备份系统的方法

    linux自动备份shell(使用全备份,增量备份策略) 在cron里设置,每周日晚12点执行(每周日全备份,其余时间增量备份)#vi backup.sh #!/bin/bash # definewe ...

  3. rsyn文件传输

    Rsync的命令格式可以为以下六种: rsync [OPTION]... SRC DEST rsync [OPTION]... SRC [USER@]HOST:DEST rsync [OPTION]. ...

  4. p1516&poj1061&bzoj1477 青蛙的约会

    传送门(洛谷) 题目 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情 ...

  5. Spring入门第二十三课

    我们看基于XML配置的方式配置AOP 看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int ad ...

  6. c++中Int装string

    java中,string类型非常强大,任何类型和string类型相加都变成了string类型.但是c++中string功能就比较少 int转string有两种方式 1:stringstream; ; ...

  7. C++ STL 的各结构实现

    C++ STL 的实现: 1.vector  底层数据结构为数组 ,支持快速随机访问 2.list    底层数据结构为双向链表,支持快速增删 3.deque   底层数据结构为一个中央控制器和多个缓 ...

  8. 自签名配置HTTPS

    基于AFN3.0 1.将后台提供的.cer文件文件保存至本地 2.在封装的网络请求工具类中为AFN的AFSecurityPolicy属性赋值 -(AFSecurityPolicy *)customSe ...

  9. Dapper.Common基于Dapper的开源LINQ超轻量扩展

    Dapper.Common Dapper.Common是基于Dapper的LINQ实现,支持.net core,遵循Linq语法规则.链式调用.配置简单.上手快,支持Mysql,Sqlserver(目 ...

  10. Unity中限制轴向移动范围Mathf.Clamp

    Mathf.Clamp   在游戏中,为了限制玩家的某一轴向的移动不超过一定的范围,可以用Mathf.Clamp来解决 Mathf.Clamp(float value,float min,float ...