重试机制
针对乐观锁的重试机制我分成以下几个步骤来实现:
- 自定义注解
- 给注解添加aop切面,在around中添加业务处理;
- 给serviceImpl添加注解
自定义注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomRetry {
//重试次数 ,这里默认15
int value() default 15;
}
简单介绍一下这几个注解的意思:
@Target 表示这个注解作用的范文,这里是作用到方法和类上面;
@Retention标志这个注解的生命周期,这里是在运行时;
@Document 表示可以被文档化;
自定义异常
public class TryAgainException extends RuntimeException {
public TryAgainException(String e) {
super(e);
}
}
添加aop切面
添加pointCut ;
/**
* 定义切点
*/
@Pointcut("@annotation(com.ht.erp.annotations.CustomRetry)")
private void customRetryPointCut() {
}
添加around 环绕通知
@Around("customRetryPointCut()&& @annotation(customRetry)")
@Transactional(rollbackFor = Exception.class)
public Object retry(ProceedingJoinPoint joinPoint, CustomRetry customRetry) throws Throwable {
int count = 0;
do {
count++;
try {
log.info("重试次数:{}", count);
return joinPoint.proceed();
} catch (TryAgainException e) {
if(count>=customRetry.value()){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new TryAgainException("重试失败");
}
}
}
while (true);
}
在serviceImpl上添加CustomRetry自定义注解,并针对版本号不一致时抛出我们自定义的异常;
@Transactional(rollbackFor = TryAgainException.class)
@CustomRetry
public void mult(int id) {
GoodsIn goodsIn = goodsInMapper.getGoodInById(id);
log.info("版本号version:" + goodsIn.getVersion());
goodsIn.setTotalNumber(goodsIn.getTotalNumber() - 1);
int i = goodsInMapper.updateGoodIn(JSON.parseObject(JSON.toJSONString(goodsIn), Map.class));
if(i==0){
throw new TryAgainException("更新异常,版本号不一致");
}
}
接下来我用jmeter发送70个并发请求测试一下,我们发现当出现版本号异常时就会出发重试。
超过了我们的重试次数之后,就会执行我定义的抛出异常;
以上只是个demo。具体业务还需具体处理;