注解方式实现
1、使用redission实现加锁和解锁逻辑
public interface DistributedLocker {
RLock lock(String lockKey);
RLock lock(String lockKey, int timeout);
RLock lock(String lockKey, TimeUnit unit, int timeout);
boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime);
void unlock(String lockKey);
void unlock(RLock lock);
}
@Service
public class RedissonDistributedLocker implements DistributedLocker {
@Autowired
private RedissonClient redissonClient;
@Override
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
@Override
public RLock lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
return lock;
}
@Override
public RLock lock(String lockKey, TimeUnit unit , int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
@Override
public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
//漏洞修复
Thread.currentThread().interrupt();
return false;
}
}
@Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
@Override
public void unlock(RLock lock) {
lock.unlock();
}
}
2、创建注解
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DistributedLock {
//锁名称
String lockName();
//等待时间
int waitTime() default 5 * 1000;
//释放时间
int leaseTime() default 5 * 1000;
//时间单位
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
3、使用aop,对注解进行拦截
@Aspect
@Component
public class DistributedLockAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(DistributedLockAspect.class);
@Autowired
private DistributedLocker distributedLocker;
@Pointcut("@annotation(com.service.aop.DistributedLock)")
public void RlockAspect() {
// DO Nothing
}
@Around("RlockAspect()")
public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object object = null;
RLock rLock = null;
try {
DistributedLock rlockInfo = getRlockInfo(proceedingJoinPoint);
if (null != rlockInfo) {
rLock = distributedLocker.lock(rlockInfo.lockName(), rlockInfo.timeUnit(), rlockInfo.leaseTime());
LOGGER.info("rlockAspect rLock start " + Thread.currentThread().getName());
object = proceedingJoinPoint.proceed();
}
} catch (Throwable e) {
e.printStackTrace();
LOGGER.error("rlockAspect rLock error",e);
throw e;
} finally {
// 当前线程获取到锁再释放锁
if (rLock != null && rLock.isHeldByCurrentThread()) {
rLock.unlock();
LOGGER.info("rlockAspect end " + Thread.currentThread().getName());
}
}
return object;
}
public DistributedLock getRlockInfo(ProceedingJoinPoint proceedingJoinPoint) {
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(DistributedLock.class);
}
}
4、使用
方法上加注解即可
@DistributedLock(lockName = "addDatasource")