注解分布式锁Redisson

目录

1、annotation

2、切面aspect

3、使用


1、annotation

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DLock {

    /**
     * 锁字符串值 可多个锁 顺序取
     * @return
     */
    String[] value();

    /**
     * 等待锁时长 秒
     * @return
     */
    int timeOut() default 30;

    /**
     * 锁定时长 秒
     * @return
     */
    int lockTime() default 60;
}

2、切面aspect


import com.lw.code.auth.annotation.DLock;
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.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Order(1)
@Aspect
@Component
public class DLockAspect {

    private final static String LOCK_PREFIX = "DLOCK:";

    /** 方法参数名解析 */
    private final static LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();

    @Resource
    private RedissonClient redissonClient;

    @Around(value = "@annotation(dLock)", argNames = "proceedingJoinPoint,dLock")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, DLock dLock) throws Throwable {
        return doLock(proceedingJoinPoint, dLock);
    }

    private Object doLock(ProceedingJoinPoint proceedingJoinPoint, DLock dLock) throws Throwable {
        /* 获取拦截方法 参数 */
        Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
        Object[] params = proceedingJoinPoint.getArgs();

        /* 创建上下文 */
        String[] paraNameArray = parameterNameDiscoverer.getParameterNames(method);
        StandardEvaluationContext context = new StandardEvaluationContext();
        if (paraNameArray != null) {
            for (int i = 0; i < paraNameArray.length; i++) {
                context.setVariable(paraNameArray[i], params[i]);
            }
        }

        /* 创建解析器 */
        ExpressionParser parser = new SpelExpressionParser();

        /* 解析锁 */
        List<RLock> rLockList = new ArrayList<>(dLock.value().length);
        for (String oriLockString : dLock.value()) {
            String lockString = parser.parseExpression(oriLockString, new TemplateParserContext()).getValue(context, String.class);
            rLockList.add(redissonClient.getFairLock(LOCK_PREFIX + lockString));
        }

        /* 加锁数量 */
        int lockNumber = 0;

        try {
            /* 尝试加锁 */
            for (RLock lock : rLockList) {
                boolean isLock = false;

                try {
                    isLock = lock.tryLock(dLock.timeOut(), dLock.lockTime(), TimeUnit.SECONDS);
                } catch (InterruptedException ie) {
                    log.error(ie.getMessage(), ie);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }

                /* 加锁失败 */
                if (!isLock) {
                    throw new RuntimeException("分布式锁加锁失败");
                }

                lockNumber++;
            }

            /* 执行业务 */
            return proceedingJoinPoint.proceed();
        } finally {
            /* 解锁 */
            if (lockNumber > 0) {
                /* 解锁数量 */
                int unLockNumber = 0;

                for (RLock lock: rLockList) {
                    try {
                        lock.unlock();
                    } catch (IllegalMonitorStateException imse) {
                        log.error(imse.getMessage(), imse);
                        // "警告 - 分布式锁:%s, 发生多持锁现象", lock.getName();
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        // 未知锁异常
                    }
                    unLockNumber++;

                    /* 解锁到未加锁部分 */
                    if (unLockNumber >= lockNumber) {
                        break;
                    }
                }
            }
        }
    }
}

3、使用


    @DLock(DLockConstants.ORDER_PAY+ "#{#orderId}")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值