中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring boot redis分布式鎖

發布時間:2020-09-28 15:16:11 來源:網絡 閱讀:916 作者:liuhanling 欄目:軟件技術

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順序執行.

spring boot redis分布式鎖

代碼如下:

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().parseExpression(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


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

贵德县| 仪陇县| 蒙阴县| 株洲县| 安陆市| 青田县| 绥芬河市| 周至县| 白玉县| 阳东县| 惠来县| 临澧县| 乐昌市| 河北区| 乌兰察布市| 宜宾县| 嘉兴市| 敦化市| 高雄县| 安吉县| 永清县| 合水县| 盘锦市| 张北县| 建瓯市| 马边| 绵竹市| 苗栗市| 游戏| 南郑县| 交口县| 邵阳县| 阳谷县| 扬州市| 封丘县| 泉州市| 岳阳市| 石城县| 靖宇县| 喀什市| 剑阁县|