@lock注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Lock {
String name();
long waitTime() default 1;
long leaseTime() default -1;
TimeUnit timeUnit() default TimeUnit.SECONDS;
boolean autoUnlock() default true;
LockType lockType() default LockType.DEFAULT;
LockStrategy lockStrategy() default LockStrategy.FAIL_AFTER_RETRY_TIMEOUT;
}
LockAspect
@Aspect
public class LockAspect {
private final RedissonClient redissonClient;
public LockAspect(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@Around("@annotation(properties)")
public Object handleLock(ProceedingJoinPoint pjp, Lock properties) throws Throwable {
if (!properties.autoUnlock() && properties.leaseTime() <= 0) {
throw new BizIllegalException("leaseTime不能为空");
}
String name = getLockName(properties.name(), pjp);
RLock rLock = properties.lockType().getLock(redissonClient, name);
boolean success = properties.lockStrategy().tryLock(rLock, properties);
if (!success) {
return null;
}
try {
return pjp.proceed();
} finally {
if (properties.autoUnlock()) {
rLock.unlock();
}
}
}
private static final Pattern pattern = Pattern.compile("\#\{([^\}]*)\}");
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private String getLockName(String name, ProceedingJoinPoint pjp) {
if (StringUtils.isBlank(name) || !name.contains("#")) {
return name;
}
EvaluationContext context = new MethodBasedEvaluationContext(
TypedValue.NULL, resolveMethod(pjp), pjp.getArgs(), parameterNameDiscoverer);
ExpressionParser parser = new SpelExpressionParser();
Matcher matcher = pattern.matcher(name);
while (matcher.find()) {
String tmp = matcher.group();
String group = matcher.group(1);
Expression expression = parser.parseExpression(group.charAt(0) == 'T' ? group : "#" + group);
Object value = expression.getValue(context);
name = name.replace(tmp, ObjectUtils.nullSafeToString(value));
}
return name;
}
private Method resolveMethod(ProceedingJoinPoint pjp) {
MethodSignature signature = (MethodSignature)pjp.getSignature();
Class<?> clazz = pjp.getTarget().getClass();
String name = signature.getName();
Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
return tryGetDeclaredMethod(clazz, name, parameterTypes);
}
private Method tryGetDeclaredMethod(Class<?> clazz, String name, Class<?> ... parameterTypes){
try {
return clazz.getDeclaredMethod(name, parameterTypes);
} catch (NoSuchMethodException e) {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
return tryGetDeclaredMethod(superClass, name, parameterTypes);
}
}
return null;
}
}
LockStrategy(加锁策略枚举)
public enum LockStrategy {
SKIP_FAST() {
@Override
public boolean tryLock(RLock lock, Lock properties) throws InterruptedException {
return lock.tryLock(0, properties.leaseTime(), properties.timeUnit());
}
},
FAIL_FAST() {
@Override
public boolean tryLock(RLock lock, Lock properties) throws InterruptedException {
boolean success = lock.tryLock(0, properties.leaseTime(), properties.timeUnit());
if (!success) {
throw new BizIllegalException("请求太频繁");
}
return true;
}
},
SKIP_AFTER_RETRY_TIMEOUT() {
@Override
public boolean tryLock(RLock lock, Lock properties) throws InterruptedException {
return lock.tryLock(properties.waitTime(), properties.leaseTime(), properties.timeUnit());
}
},
FAIL_AFTER_RETRY_TIMEOUT() {
@Override
public boolean tryLock(RLock lock, Lock properties) throws InterruptedException {
boolean success = lock.tryLock(properties.waitTime(), properties.leaseTime(), properties.timeUnit());
if (!success) {
throw new BizIllegalException("请求超时");
}
return true;
}
},
KEEP_RETRY() {
@Override
public boolean tryLock(RLock lock, Lock properties) throws InterruptedException {
lock.lock(properties.leaseTime(), properties.timeUnit());
return true;
}
},
;
public abstract boolean tryLock(RLock lock, Lock properties) throws InterruptedException;
}
LockType(锁类型枚举)
public enum LockType {
DEFAULT(){
@Override
public RLock getLock(RedissonClient redissonClient, String name) {
return redissonClient.getLock(name);
}
},
FAIR_LOCK(){
@Override
public RLock getLock(RedissonClient redissonClient, String name) {
return redissonClient.getFairLock(name);
}
},
READ_LOCK(){
@Override
public RLock getLock(RedissonClient redissonClient, String name) {
return redissonClient.getReadWriteLock(name).readLock();
}
},
WRITE_LOCK(){
@Override
public RLock getLock(RedissonClient redissonClient, String name) {
return redissonClient.getReadWriteLock(name).writeLock();
}
},
;
public abstract RLock getLock(RedissonClient redissonClient, String name);
}
```