0
点赞
收藏
分享

微信扫一扫

QT 带箭头的控件QPolygon

一叶轻舟okok 2024-09-21 阅读 49

文章目录

前言

在分布式锁的实现中,通常会使用Redisson实现。但每次使用都会写下面的这种逻辑。

RLock rLock = null;
try {
	rLock = redissonClient.getLock(lockKeyExpr);
	boolean lockFlag = rLock.tryLock(waitTime, timeUnit);
	if (!lockFlag ) {
		return;
	}
} finally {
	if (Objects.nonNull(rLock )) {
		 rLock.unlock();
	}
}

每次要调用都需要这么写,显得很繁琐。故此本篇博客采取自定义注解的方式,简化实现逻辑,只需要保证在使用处标记对应的注解即可实现。

代码实现

依赖引入

<!-- 分布式锁相关 -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.16.0</version>
</dependency>

自定义分布式锁注解

编写自定义注解,需要考虑到EL表达式超时时间超时时间单位信息。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁注解
 * @author xf.wu
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Lock {

    /**
     * spel 表达式
     * @return
     */
    String lockKeyExpr() default "redisson_lock";

    /**
     * 时间值
     * @return
     */
    long waitTime() default 5000L;

    /**
     * 时间单位 毫秒
     * @return
     */
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}

aop切面切点处理逻辑

注解只是一个标签,没有具体的实现逻辑就会毫无用处。

import cn.hutool.core.util.ArrayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.beans.factory.annotation.Autowired;
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁  注解配置 aop 
 * @Author xf.wu
 */
@Slf4j
@Aspect
@Component
public class LockConfig {

    private static final String SPEL_STR = "^#.*.$";

    @Autowired
    private RedissonClient redissonClient;

    /**
     * rlock 切面切点
     * @param joinPoint 切面切点point
     * @param redisLock rlock 类
     */
    @Around("@annotation(redisLock)")
    public Object aroundLock(ProceedingJoinPoint joinPoint, Lock redisLock) throws Throwable {
        log.info("---->进入lock-----");
        String lockKeyExpr  = redisLock.lockKeyExpr();
        long waitTime = redisLock.waitTime();
        TimeUnit timeUnit = redisLock.timeUnit();
        Object[] args = joinPoint.getArgs();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		// 1、如果未指定key名称,给定默认值
        if (StringUtils.isBlank(lockKeyExpr)) {
            lockKeyExpr = "redisson_lock";
        }
		// 2、若指定 lockKeyExpr=#xxxx ,则需要按照spel表达式解析接口传值
        if (lockKeyExpr.matches(SPEL_STR)) {
            StandardReflectionParameterNameDiscoverer discoverer = new StandardReflectionParameterNameDiscoverer();
            String[] paraNameArr = discoverer.getParameterNames(method);
            paraNameArr = (ArrayUtil.isEmpty(paraNameArr)) ? new String[]{} : paraNameArr;

            StandardEvaluationContext context = new StandardEvaluationContext();
            for (int i = 0; i < Objects.requireNonNull(paraNameArr).length; i++) {
                context.setVariable(paraNameArr[i], args[i]);
            }

            ExpressionParser parser = new SpelExpressionParser();
            lockKeyExpr = parser.parseExpression(lockKeyExpr).getValue(context, String.class);
        }

        Object obj = null;
        RLock rLock = null;
        try {
            lockKeyExpr = lockKeyExpr + ":LOCK_KEY";
            rLock = redissonClient.getLock(lockKeyExpr);
            boolean lockFlag = rLock.tryLock(waitTime, timeUnit);
            log.info("----- 拿锁:{}",lockFlag);
            // 判断是否拿到锁  没有拿到则直接退出,避免阻塞
            if (lockFlag) {
            	// 3、拿到锁则进入对应的service处理方法
                obj = joinPoint.proceed();
            }
        } finally {
            if (Objects.nonNull(rLock) && rLock.isLocked() && rLock.isHeldByCurrentThread()) {
                log.info("----- 释放锁");
                rLock.unlock();
            }
        }
        return obj;
    }
}

自定义锁注解的使用

不使用el表达式解析

@Lock(lockKeyExpr="lockname",waitTime=4000L)

使用EL表达式解析

@Lock(lockKeyExpr="#user.id",waitTime=4000L)
举报

相关推荐

0 条评论