Redisson注解锁
使用
调用方式使用
java
public void lockFunction() throws InterruptedException {
redissonLockService.executeWithLock("lockKey",3,TimeUnit.SECONDS, () -> {
// 执行业务逻辑
log.info("获取到分布式锁,开始执行业务逻辑");
return null;
});
}
注解方式使用
java
@RedissonLock(key = "lockKey", prefixKey = "lockPrefix", waitTime = 3)
public void lockFunction() throws InterruptedException {
log.info("获取到分布式锁,开始执行业务逻辑");
}
代码
注解
java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RedissonLock {
/**
* key的前缀,默认取方法全限定名
*
* @return key的前缀
*/
String prefixKey() default "";
/**
* springEl 表达式
*
* @return 表达式
*/
String [] key();
/**
* 获取锁的等待时间,单位秒
*/
int waitTime() default -1;
}
AOP
java
@Slf4j
@AllArgsConstructor
@Aspect
@Order(0) // 确保分布式锁最先执行
@Component
public class RedissonLockAspect {
private final RedissonLockService redissonLockService;
@Around("@annotation(com.ruoyi.common.annotation.RedissonLock)")
public Object around(ProceedingJoinPoint point) throws Throwable {
log.info("进入分布式锁AOP处理方法: {}", point.getSignature().toShortString());
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
// 获取注解信息
RedissonLock methodAnnotation = method.getAnnotation(RedissonLock.class);
// 获取前缀
String prefixKey = methodAnnotation.prefixKey();
// 获取key
String[] keys = methodAnnotation.key();
// el 解析
ExpressionParser parser = new SpelExpressionParser(); // el解析器
DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); // 参数名解析器
StandardEvaluationContext context = new StandardEvaluationContext(); // el解析需要的上下文对象
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
// 参数添加到上下文
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], point.getArgs()[i]);
}
}
// 解析每个key
String key = Arrays.stream(keys).map(k -> {
Expression expression = parser.parseExpression(k);
return expression.getValue(context, String.class);
})
.filter(Objects::nonNull)
.collect(Collectors.joining("_", prefixKey+"_", ""));
// 获取等待时间和过期时间
int waitTime = methodAnnotation.waitTime();
return redissonLockService.executeWithLock(key, waitTime, TimeUnit.SECONDS, () -> {
try {
// 执行目标方法
return point.proceed();
} catch (Throwable throwable) {
// 如果有异常,抛出运行时异常
log.error("执行方法时发生异常: {}", throwable);
throw new ServiceException("执行方法时发生异常: " + throwable.getMessage());
}
});
}
}
锁实现
java
@Slf4j
@Service
@AllArgsConstructor
public class RedissonLockService {
private final Redisson redisson;
/**
* 默认分布式锁等待时间 10秒
*/
private static final int LOCK_DEFAULT_WAIT_TIME =10 ;
/**
* 执行带分布式锁的操作 默认等待时间为10秒
* @param key 分布式锁的唯一标识
* @param supplier 执行的操作,返回结果
* @return
*/
public <T> T executeWithLock(String key, Supplier<T> supplier) throws InterruptedException,ServiceException {
return executeWithLock(key, LOCK_DEFAULT_WAIT_TIME, TimeUnit.SECONDS, supplier);
}
/**
* 执行带分布式锁的操作
* @param key 分布式锁的唯一标识
* @param waitTime 获取锁的等待时间
* @param timeUnit 获取锁的时间单位
* @param supplier 执行的操作,返回结果
*/
public <T> T executeWithLock(String key, Integer waitTime, TimeUnit timeUnit, Supplier<T> supplier) throws InterruptedException, ServiceException {
// 尝试获取锁
RLock lock = redisson.getLock(key);
boolean tryLock = lock.tryLock(waitTime, timeUnit);
if (!tryLock) {
throw new ServiceException("获取分布式锁失败");
}
try {
return supplier.get();
} finally {
// 确保释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}