aap手机网站建设,一个主体可以备案几个网站,为什么学网站开发,专业的公司网页制作文章目录 前言代码实现依赖引入自定义分布式锁注解aop切面切点处理逻辑 自定义锁注解的使用不使用el表达式解析使用EL表达式解析 前言
在分布式锁的实现中#xff0c;通常会使用Redisson实现。但每次使用都会写下面的这种逻辑。
RLock rLock null;
try {rLock redissonCli… 文章目录 前言代码实现依赖引入自定义分布式锁注解aop切面切点处理逻辑 自定义锁注解的使用不使用el表达式解析使用EL表达式解析 前言
在分布式锁的实现中通常会使用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();}
}每次要调用都需要这么写显得很繁琐。故此本篇博客采取自定义注解的方式简化实现逻辑只需要保证在使用处标记对应的注解即可实现。
代码实现
依赖引入
!-- 分布式锁相关 --
dependencygroupIdorg.redisson/groupIdartifactIdredisson-spring-boot-starter/artifactIdversion3.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 ^#.*.$;Autowiredprivate 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(lockKeyExprlockname,waitTime4000L)使用EL表达式解析
Lock(lockKeyExpr#user.id,waitTime4000L)