一 创建RedissonLock注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonLock {
String cacheName();
String key();
long timeOutTTL() default 60;
}
二 将注册声明到需要修改的保存方法上
@Transactional(rollbackFor = Exception.class)
@RedissonLock(cacheName = "#xxxCacheName", key = "#request.xxxCode,#request.xxxName")
public Boolean xxxAdd(AddDTO add) {
//TODO
}
三 注册切面
@Aspect
@AllArgsConstructor
@Component
public class RedissonLockAspect {
@Autowired
private RedissonClient redissonClient;
//新增注解的全限定类名
@Pointcut("@annotation(com.xxx.xxx.xxx.redisson.RedissonLock)")
public void lockAspect(){
}
@Around("lockAspect()")
public void doAround(ProceedingJoinPoint point) throws Throwable{
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
String[] paramNames = signature.getParameterNames();
Object[] args = point.getArgs();
TreeMap<String,Object> treeMap = new TreeMap<>();
for(int i=0;i< paramNames.length;i++){
treeMap.put(paramNames[i],args[i]);
}
RedissonLock annotation = method.getAnnotation(RedissonLock.class);
String key = annotation.key();
StringBuilder stringBuilder = new StringBuilder();
if(key.contains(RedissonContext.KEY_SPLIT)){
String split = "";
for(String value : key.split(RedissonContext.KEY_SPLIT)){
//通过EL表达式获取方法注解上参数对用的值,用来作为锁的key
stringBuilder.append(split).append(StringElBuild.parseElString(value,treeMap));
split = RedissonContext.KEY_SPLIT;
}
} else {
stringBuilder.append(StringElBuild.parseElString(key,treeMap));
}
//上锁
RLock lock = redissonClient.getLock(stringBuilder.toString());
if(lock.tryLock()){
//执行业务逻辑
point.proceed();
} else {
throw new BusinessException(BasicErrorCode.SYSTEM_BUSY);
}
//释放锁
if(lock.isLocked()){
lock.unlock();
}
}
}
四 设置EL表达式
public class StringElBuild {
public static String parseElString(String elString, TreeMap<String,Object> map){
elString = String.format("#{%s}",elString);
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
map.entrySet().forEach(entry ->
context.setVariable(entry.getKey(),entry.getValue())
);
Expression expression = parser.parseExpression(elString, new TemplateParserContext());
String value = expression.getValue(context,String.class);
return value;
}
}