zoukankan      html  css  js  c++  java
  • Redisson锁

    @RedisLock(lockName = "device_goods_stock",key="'skuId:'+#skuId" , expire = 2000)

    /*
    * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
    *
    * https://www.gz-yami.com/
    *
    * 未经允许,不可做商业用途!
    *
    * 版权所有,侵权必究!
    */

    package com.box.lock.annotation;

    import java.lang.annotation.*;
    import java.util.concurrent.TimeUnit;

    /**
    * 使用redis进行分布式锁
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RedisLock {

    /**
    * redis锁 名字
    */
    String lockName() default "";

    /**
    * redis锁 key 支持spel表达式
    */
    String key() default "";

    /**
    * 过期秒数,默认为5毫秒
    *
    * @return 轮询锁的时间
    */
    int expire() default 5000;

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



    /*
    * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
    *
    * https://www.gz-yami.com/
    *
    * 未经允许,不可做商业用途!
    *
    * 版权所有,侵权必究!
    */

    package com.box.lock.aspect;

    import cn.hutool.core.util.ArrayUtil;
    import cn.hutool.core.util.StrUtil;
    import com.box.lock.annotation.RedisLock;
    import org.apache.commons.lang.StringUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    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.context.expression.MethodBasedEvaluationContext;
    import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
    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;

    /**
    * @author yuandingwang
    */
    @Aspect
    @Component
    public class RedisLockAspect {

    @Autowired
    private RedissonClient redissonClient;

    private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";

    @Around("@annotation(redisLock)")
    public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
    String spel = redisLock.key();
    String lockName = redisLock.lockName();

    RLock rLock = redissonClient.getLock(getRedisKey(joinPoint, lockName, spel));
    rLock.lock(redisLock.expire(), redisLock.timeUnit());

    Object result = null;
    try {
    //执行方法
    result = joinPoint.proceed();
    // System.out.println("分布式锁");
    } finally {
    rLock.unlock();
    }
    return result;
    }

    /**
    * 将spel表达式转换为字符串
    *
    * @param joinPoint 切点
    * @return redisKey
    */
    private String getRedisKey(ProceedingJoinPoint joinPoint, String lockName, String spel) {
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method targetMethod = methodSignature.getMethod();
    Object target = joinPoint.getTarget();
    Object[] arguments = joinPoint.getArgs();
    return REDISSON_LOCK_PREFIX + lockName + StrUtil.COLON + parse(target, spel, targetMethod, arguments);
    }

    private static String parse(Object rootObject,String spel, Method method, Object[] args) {
    if (StringUtils.isBlank(spel)) {
    return StrUtil.EMPTY;
    }
    //获取被拦截方法参数名列表(使用Spring支持类库)
    LocalVariableTableParameterNameDiscoverer u =
    new LocalVariableTableParameterNameDiscoverer();
    String[] paraNameArr = u.getParameterNames(method);
    if (ArrayUtil.isEmpty(paraNameArr)) {
    return spel;
    }
    //使用SPEL进行key的解析
    ExpressionParser parser = new SpelExpressionParser();
    //SPEL上下文
    StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject,method,args,u);
    //把方法参数放入SPEL上下文中
    for (int i = 0; i < paraNameArr.length; i++) {
    context.setVariable(paraNameArr[i], args[i]);
    }
    return parser.parseExpression(spel).getValue(context, String.class);
    }
    }

    }
    小蚊子大人
  • 相关阅读:
    上机课前准备
    C# 跨线程访问控件的解决方法
    C# 异步和多线程的区别
    C# BeginInvoke和EndInvoke方法
    C# 委托的回调机制
    C# 什么是委托
    C# WebBrowser的控件使用
    C# 解决WebBrowser.DocumentCompleted事件的多次调用
    平台调用数据类型
    C# 创建快捷方式
  • 原文地址:https://www.cnblogs.com/ywsheng/p/14975800.html
Copyright © 2011-2022 走看看