1.注解interface
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RdsLock {
String value();
String type();
}
2.定义aop
import common.saas.base.constant.ErrorConstant;
import common.saas.util.Assert;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
@Slf4j
@Aspect
@Component
public class RedisLockAop {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Pointcut("@annotation(com.saas.aop.RdsLock)")
public void lockPiontCut() {
}
@Around("lockPiontCut() && @annotation(rdsLock)")
public Object lock(ProceedingJoinPoint point, RdsLock rdsLock) throws Throwable {
Object[] args = point.getArgs();
Method readMethod = BeanUtils.getPropertyDescriptor(args[0].getClass(), rdsLock.type()).getReadMethod();
Object typeValue = readMethod.invoke(args[0]);
String locKey = String.format(rdsLock.value(), typeValue.toString());
Boolean isLock = stringRedisTemplate.opsForValue().setIfAbsent(locKey, "lock", 10L, TimeUnit.SECONDS);
if (isLock) {
log.info("开启redis线程锁{}", locKey);
} else {
log.info("线程已被占用:{}", locKey);
Assert.notNUll(null, ErrorConstant.C401, ErrorConstant.M401, "请勿重复提交,请稍后再试");
}
Object result;
try {
result = point.proceed();
} catch (Exception e) {
stringRedisTemplate.delete(locKey);
log.info("删除redis线程锁{}", locKey);
throw e;
}
stringRedisTemplate.delete(locKey);
log.info("删除redis线程锁{}", locKey);
return result;
}
}
3.使用
@RdsLock(type = "切面获取service method使用,要求唯一,作为redis锁的key1", value = "redis锁的key2")
redis锁key=key2:key1
示例:
@RdsLock(type = "orderNo", value = "(可定义为常量)member:account:marketing:order:%s")
@Override
@RdsLock(type = "orderNo", value = RedisConstant.MEMBER_ACCOUNT_MARKETING_ORDER)
public Result addBean(BeanOrderReq beanOrderReq) {
// serviceImpl接口的业务代码
}



