进行在事务之前加锁,那就是AOP
自定义AOP注解
@Target({ElementType.PARAMETER, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interface ServiceLock {
String description() default"";
}
定义切面类
@Slf4j
@Component@Scope@Aspect@Order(1) //order越小越是最先执行,但更重要的是最先执行的最后结束publicclassLockAspect{
/**
* 思考:为什么不用synchronized
* service 默认是单例的,并发下lock只有一个实例
*/privatestatic Lock lock = new ReentrantLock(true); // 互斥锁 参数默认false,不公平锁// Service层切点 用于记录错误日志@Pointcut("@annotation(com.scorpios.secondkill.aop.ServiceLock)")
publicvoidlockAspect(){
}
@Around("lockAspect()")
public Object around(ProceedingJoinPoint joinPoint){
lock.lock();
Object obj = null;
try {
obj = joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
thrownew RuntimeException();
} finally{
lock.unlock();
}
return obj;
}
}
在业务方法上添加AOP注解
@Override@ServiceLock// 使用Aop进行加锁@Transactional(rollbackFor = Exception.class)
publicResultstartSecondKillByAop(longskgId, longuserId) {
try {
// 校验库存
SecondKill secondKill = secondKillMapper.selectById(skgId);
Integer number = secondKill.getNumber();
if (number > 0) {
//扣库存
secondKill.setNumber(number - 1);
secondKillMapper.updateById(secondKill);
//创建订单
SuccessKilled killed = new SuccessKilled();
killed.setSeckillId(skgId);
killed.setUserId(userId);
killed.setState((short) 0);
killed.setCreateTime(new Timestamp(System.currentTimeMillis()));
successKilledMapper.insert(killed);
//支付
Payment payment = new Payment();
payment.setSeckillId(skgId);
payment.setSeckillId(skgId);
payment.setUserId(userId);
payment.setMoney(40);
payment.setState((short) 1);
payment.setCreateTime(new Timestamp(System.currentTimeMillis()));
paymentMapper.insert(payment);
} else {
return Result.error(SecondKillStateEnum.END);
}
} catch (Exception e) {
thrownew ScorpiosException("异常了个乖乖");
}
return Result.ok(SecondKillStateEnum.SUCCESS);
}
控制层:
@ApiOperation(value="秒杀实现方式二——Aop加锁")
@PostMapping("/start/aop")
public Result startAop(long skgId){
try {
log.info("开始秒杀方式二...");
finallong userId = (int) (new Random().nextDouble() * (99999 - 10000 + 1)) + 10000;
Result result = secondKillService.startSecondKillByAop(skgId, userId);
if(result != null){
log.info("用户:{}--{}", userId, result.get("msg"));
}else{
log.info("用户:{}--{}", userId, "哎呦喂,人也太多了,请稍后!");
}
} catch (Exception e) {
e.printStackTrace();
}
return Result.ok();
}
这种方式在对锁的使用上,更高阶、更美观!