项目AOP 幂等性
注意:是通过自定义注释实现的,在需要实现幂等性的方法上添加注释
一、准备
- 自定义注解
@Idempotent
,用于标识需要幂等性控制的方法。
- 定义AOP切面类
- 使用
@Aspect
定义切面,拦截使用 @Idempotent
注解的方法,确保幂等性。
二、调用
1.在需要幂等性的接口方法上使用这个注释
2.在应用启动的时候,spring会自动的扫描并注册aop切面类’**IdempotentAopHandler
**
- 当调用标记了
@Idempotent
注解的方法时,AOP 切面会拦截调用,检查 Redis 中是否存在锁,如果不存在则设置锁并执行方法,执行完毕后释放锁。
3.获取唯一的标识
- 从
@Idempotent
注解中获取 uniqueIdentification
,结合当前用户的 Token 生成幂等性锁标识。
4.尝试获得锁
- 调用
redisUtil.setIfAbsentEx
方法尝试在 Redis 中设置一个带有过期时间的键,如果设置成功,则表示获取到锁。
5.执行方法
- 获取锁成功后,执行目标方法。
- 如果方法执行过程中抛出异常,记录日志并抛出自定义异常。
6.释放锁:
- 方法执行完毕后,无论是否成功,都会在
finally
块中删除 Redis 锁,确保锁被释放。
7.异常处理
- 如果未能获取到锁,抛出自定义异常,表示该方法在指定时间内不能重复执行。
通过这种方式,可以确保方法在指定的时间窗口内只会执行一次,防止重复提交或重复调用,保证接口的幂等性。
三、代码
在代码里是在AOP切面编程中,使用了redis的分布式锁来实现最终一个结果,就是redis的操作的幂等性,这个redis只是我的猜测,保证在并发情况下只执行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package top.quhailong.pan.framework.redis.core.idempotent.aop; @Order(1) @Aspect @Slf4j class IdempotentAopHandler { @Autowired private RedisUtil redisUtil;
@Pointcut("@annotation(top.quhailong.pan.framework.redis.core.idempotent.annotation.Idempotent)") public void IdempotentPointCut() { }
@Around("IdempotentPointCut()") public Object addIdempotent(ProceedingJoinPoint proceedingJoinPoint) { Object result = null;
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = signature.getMethod(); Idempotent idempotent = method.getAnnotation(Idempotent.class); String uniqueIdentification = idempotent.uniqueIdentification();
String idempotentLock = String.format(RedisConstants.IDEMPOTENT_LOCK, uniqueIdentification, TokenUtil.getToken());
if (redisUtil.setIfAbsentEx(idempotentLock, UUID.randomUUID().toString(), 120, TimeUnit.SECONDS)) { try { result = proceedingJoinPoint.proceed();
} catch (Throwable e) { log.error("业务处理出现异常", e); throw new CustomException(ResultCodeEnum.SERVICE_EXCEPTION.getCode(), ResultCodeEnum.SERVICE_EXCEPTION.getDesc()); } finally { redisUtil.delete(idempotentLock);
} } else { throw new CustomException(ResultCodeEnum.IDEMPOTENT_LOCK_ERROR.getCode(), ResultCodeEnum.IDEMPOTENT_LOCK_ERROR.getMessage()); } return result; } }
|
四、一些细节
方法签名
方法签名是编程中描述一个方法的特征的方式,它标识方法的名称以及方法的参数的类型顺序,在java中,方法签名不包括方法的返回类型和访问修饰符,
作用
AOP框架中,就是可以通过方法签名来识别和拦截方法的调用