spring boot redis分布式锁
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,spring boot redis分布式锁参照spring boot redis分布式锁 用注解实现时发现不能满足使用需求于是自己开始摸索解决问题...如下,value 是lock的key,因为业务的
千家信息网最后更新 2025年12月02日spring boot redis分布式锁
spring boot redis分布式锁
参照spring boot redis分布式锁 用注解实现时发现不能满足使用需求
于是自己开始摸索解决问题...
如下,value 是lock的key,因为业务的需要key是 "cancelOrder_123_321" 123是订单ID,321是用户ID
@RedisLock(value = "cancelOrder_#{#order.orderNo}_#{#memberId}")@Transactional(rollbackFor = {RuntimeException.class, Exception.class})public void cancelOrder(Order order, String memberId) { log.info("用户:{},订单号:{} 开始执行取消流程...",order.getOrderNo(),memberId); String orderNo = order.getOrderNo(); Order updateOrder = new Order(); updateOrder.setOrderNo(orderNo); updateOrder.setOrderState(OrderStateEnum.CANCELED.getKey());长话短说,需要了解详情的朋友看其他大神的博客
为什么我可以这样 cancelOrder_#{#order.orderNo}_#{#memberId} 写?
这里最重要的是什么?
是因为我将这个el表达式字符串,解析成了复合型了.复合型简单点就是List集合,集合里有el表达式和文本,用for顺序执行.

代码如下:
Aspect类
private static final OperationExpressionEvaluator evaluator = new OperationExpressionEvaluator();@Around("lockPoint()")public Object around(ProceedingJoinPoint pjp) throws Throwable{ Method method = ((MethodSignature)pjp.getSignature()).getMethod(); RedisLock redisLock = method.getAnnotation(RedisLock.class); String key = getKey(redisLock.value(),method,pjp.getArgs(),pjp.getTarget()); int retryTimes = redisLock.action().equals(RedisLock.LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0; boolean lock = redisLockImpl.lock(key,redisLock.keepMills(),retryTimes,redisLock.sleepMills()); if(!lock){ log.debug("get lock failed:{}",key); return null; } log.debug("get lock success:{}",key); try{ return pjp.proceed(); }catch (Exception e){ log.error("execute locked method occured an exception",e); } finally { boolean releaseResult = redisLockImpl.releaseLock(key); log.debug("release lock:{}-{}",key,releaseResult ? "success":"failed"); } return null;}private String getKey(String key,Method method,Object [] args,Object target){ if(key.length() <= 0){ return Arrays.toString(args); } return String.valueOf(generateKey(key,method,args,target));}private Object generateKey(String key,Method method,Object [] args,Object target) { EvaluationContext evaluationContext = evaluator.createEvaluationContext(method, args, target, target.getClass(), null); return evaluator.key(key, evaluationContext);}OperationExpressionEvaluator 类
/** * @author liuhanling * @create 2019-01-14 17:03 * @desc 操作表达式评估器 */public class OperationExpressionEvaluator extends CachedExpressionEvaluator{ private final ParserContext parserContext = new ParserContext() { @Override public boolean isTemplate() { return true; } @Override public String getExpressionPrefix() { return "#{"; } @Override public String getExpressionSuffix() { return "}"; } }; /** * Create an {@link EvaluationContext}. * @param method the method * @param args the method arguments * @param target the target object * @param targetClass the target class * @return the evaluation context */ public EvaluationContext createEvaluationContext(Method method, Object[] args, Object target, Class> targetClass, BeanFactory beanFactory) { //bean context ExpressionRootObject rootObject = new ExpressionRootObject(method, args, target, targetClass); //获取目标方法 Method targetMethod = getTargetMethod(targetClass, method); //评测上下文,主要是处理无用变量 MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject,targetMethod,args,getParameterNameDiscoverer()); //CacheEvaluationContext evaluationContext = new CacheEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer()); if (beanFactory != null) { evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); } return evaluationContext; } public Object key(String keyExpression, EvaluationContext evalContext) { //执行el表达式 复合型 return getParser().parse_Expression(keyExpression,parserContext).getValue(evalContext); } private Method getTargetMethod(Class> targetClass, Method method) { //AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass); //Method targetMethod = this.targetMethodCache.get(methodKey); //if (targetMethod == null) { Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); if (targetMethod == null) { targetMethod = method; } //this.targetMethodCache.put(methodKey, targetMethod); //} return targetMethod; }}ExpressionRootObject 类
/** * @author liuhanling * @create 2019-01-14 17:04 * @desc 表达式 rootObject */public class ExpressionRootObject { /** * 方法 */ private final Method method; /** * 参数数组 */ private final Object[] args; /** * 目标对象 */ private final Object target; /** * 目标类 */ private final Class> targetClass; public ExpressionRootObject(Method method, Object[] args, Object target, Class> targetClass) { Assert.notNull(method, "Method is required"); Assert.notNull(targetClass, "targetClass is required"); this.method = method; this.target = target; this.targetClass = targetClass; this.args = args; } public Method getMethod() { return this.method; } public String getMethodName() { return this.method.getName(); } public Object[] getArgs() { return this.args; } public Object getTarget() { return this.target; } public Class> getTargetClass() { return this.targetClass; }}[1]参考链接(spring boot redis分布式锁) https://my.oschina.net/dengfuwei/blog/1600681
[2]参考链接(el表达式) https://blog.csdn.net/zhoudaxia/article/details/38174169
表达式
分布式
复合型
目标
方法
用户
订单
链接
参考
重要
长话短说
上下
上下文
业务
代码
博客
参数
变量
大神
字符
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
开发环境和软件开发的区别
数据库落地
平行网络技术
直接连接数据库的优缺点
电脑直连服务器ip
维护网络安全要以什么
中国科学期刊数据库
无线网络安全可类型
同源基因数据库
宽带服务器连接设置
网评网络安全是什么意思
网络安全素养的内容包括哪些
呈贡区软件开发咨询报价
常用的重庆联通服务器托管云空间
网络安全技术设施
数据库公交查询系统作业
希腊网络安全怎么样
软考网络安全工程师考试大纲
mabits怎么调数据库
合肥嵌入式软件开发
专用服务器网络
ftp服务器映射到公网
衡水网络安全工程师招聘信息
软件开发过程视频
系统集成资质软件开发资质
软件开发用那些证书
哈工程网络安全就业
考研数据库技术类
换服务器 seo
福建定制软件开发服务商