之前我加锁是在方法里面,但是有一个问题,就是没有解耦,就跟我说redis不同mysql缓存是一样的。
这里也写一个AOP,利用注解,进行方法的加锁。
首先,写一个ASPECT
@Aspect
@Component
public class RedisLockAspect {
@Autowired
private RedissonClient redissonClient;
private static final String REDIS_PREFIX = "redisson_lock:";
@Around("@annotation(redisLock)")
public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
String key = redisLock.key();
String lockName = redisLock.lockName();
RLock rLock = redissonClient.getLock(REDIS_PREFIX + lockName + ":" + key);
rLock.lock(redisLock.expire(),redisLock.timeUnit());
Object result = null;
try {
//执行方法
result = joinPoint.proceed();
} finally {
rLock.unlock();
}
return result;
}
}
我们在测试的时候,模拟2000个并发,之前有测试代码,你们可以直接拿来用。
@GetMapping("/test/{id}")
@RedisLock(lockName = "test", key = "test + ':' + #id")
public void aspectLock(@PathVariable String id) {
//模拟多个资源请求输出库存情况
//goods_num
System.out.println("-------------线程"+id+"抢到锁------------");
//获取成功
int num = Integer
.parseInt(distributedLock.getValueByKey("goods_num"));
if(num > 0) {
distributedLock.setValueByKey("goods_num", Integer.toString(num - 1));
System.out.println("商品数剩余----->" + (num - 1));
} else {
System.out.println("商品销售完----结束了!");
}
System.out.println("-------------线程"+id+"结束------------");
}
标记了红色的,就是注解了。
可以看到,这个逻辑就解耦了,我们先获得锁,能获得锁的,那么就进入方法。
遮掩就可以了,代码简洁易懂。