Spring AOP初步总结(三)
最近遇到一个新需求:用户多次点击提交订单发生多次扣款,一开始准备配置数据库事务,但后来发现这种方法白白浪费很多资源,就改为利用接口上的切面对请求做拦截,并将当前登陆的用户存进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初步总结(三)的更多相关文章
- spring AOP详解三
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的结束拦截所有父类方法的调用,并顺势织入横切逻辑.我们采用CGLib技术可以编写一个可以为任何类创建织入横切逻辑代理对象 ...
- 深入源码解析spring aop实现的三个过程
Spring AOP的面向切面编程,是面向对象编程的一种补充,用于处理系统中分布的各个模块的横切关注点,比如说事务管理.日志.缓存等.它是使用动态代理实现的,在内存中临时为方法生成一个AOP对象,这个 ...
- Spring AOP实现方式三之自动扫描注入【附源码】
注解AOP实现 这里唯一不同的就是application 里面 不需要配置每个bean都需要配置了,直接自动扫描 注册,主要知识点是怎么通过配置文件得到bean, 注意类前面的@注解. 源码结构: ...
- Spring AOP实现方式三【附源码】
注解AOP实现 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.aop; /** * 谈恋爱接口 * * @author Administrator ...
- Spring AOP初步总结(二)
该篇为Spring AOP的一个应用案例:系统日志 需求:将任何删除,更改或新增数据库的操作汇总到数据库中 步骤1:编写切面 @Aspect @Component public class SysLo ...
- Spring AOP初步总结(一)
学习AOP有段时间了,一直没空总结一下,导致有些知识点都遗忘了,之后会把以前学过的Spring核心相关的知识点总结一轮... 先大体介绍下Spring AOP的特点(均摘自"Spring i ...
- Spring源码窥探之:Spring AOP初步
AOP(Aspect Oriented Programming):即我们常说的面向切面编程. 什么是AOP?AOP是在我们原来写的代码的基础上,进行一定的包装,比如在方法执行前.方法返回后.方法抛出异 ...
- Spring AOP 简介(三)
Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...
- Spring源码窥探之:Spring AOP初步使用
AOP即面向切面编程.它的底层实际是用了spring的动态代理,具体是JDK的代理还是CGLIB的代理,就视情况而定了.本博客园仅仅作为平时记录,显得有些杂乱无章,如果想了解动态代理,设计模式,请访问 ...
随机推荐
- C#调用ODBC连接SQL Server数据库的存储过程
OdbcConnection con = new OdbcConnection("Driver={SQL Server};server=PC-200201070359;uid=sa;pwd= ...
- shell脚本备份系统的方法
linux自动备份shell(使用全备份,增量备份策略) 在cron里设置,每周日晚12点执行(每周日全备份,其余时间增量备份)#vi backup.sh #!/bin/bash # definewe ...
- rsyn文件传输
Rsync的命令格式可以为以下六种: rsync [OPTION]... SRC DEST rsync [OPTION]... SRC [USER@]HOST:DEST rsync [OPTION]. ...
- p1516&poj1061&bzoj1477 青蛙的约会
传送门(洛谷) 题目 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情 ...
- Spring入门第二十三课
我们看基于XML配置的方式配置AOP 看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int ad ...
- c++中Int装string
java中,string类型非常强大,任何类型和string类型相加都变成了string类型.但是c++中string功能就比较少 int转string有两种方式 1:stringstream; ; ...
- C++ STL 的各结构实现
C++ STL 的实现: 1.vector 底层数据结构为数组 ,支持快速随机访问 2.list 底层数据结构为双向链表,支持快速增删 3.deque 底层数据结构为一个中央控制器和多个缓 ...
- 自签名配置HTTPS
基于AFN3.0 1.将后台提供的.cer文件文件保存至本地 2.在封装的网络请求工具类中为AFN的AFSecurityPolicy属性赋值 -(AFSecurityPolicy *)customSe ...
- Dapper.Common基于Dapper的开源LINQ超轻量扩展
Dapper.Common Dapper.Common是基于Dapper的LINQ实现,支持.net core,遵循Linq语法规则.链式调用.配置简单.上手快,支持Mysql,Sqlserver(目 ...
- Unity中限制轴向移动范围Mathf.Clamp
Mathf.Clamp 在游戏中,为了限制玩家的某一轴向的移动不超过一定的范围,可以用Mathf.Clamp来解决 Mathf.Clamp(float value,float min,float ...