SpringBoot-分布式锁

基于AOP的Redis分布式锁

锁是针对某个资源,保证其访问的互斥性,在实际使用当中,这个资源一般是一个字符串。使用 Redis 实现锁,主要是将资源放到 Redis 当中,利用其原子性,当其他线程访问时,如果 Redis 中已经存在这个资源,就不允许之后的一些操作。spring boot使用 Redis 的操作主要是通过 RedisTemplate 来实现
在实际的使用过程中,分布式锁可以封装好后使用在方法级别,这样就不用每个地方都去获取锁和释放锁,使用起来更加方便。
一·首先定义个注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RedisLock {

    /** 锁的资源,redis的key*/
    String value() default "default";

    /** 持锁时间,单位毫秒*/
    long keepMills() default 30000;

    /** 当获取失败时候动作*/
    LockFailAction action() default LockFailAction.CONTINUE;

    public enum LockFailAction{
        /** 放弃 */
        GIVEUP,
        /** 继续 */
        CONTINUE;
    }

    /** 重试的间隔时间,设置GIVEUP忽略此项*/
    long sleepMills() default 200;

    /** 重试次数*/
    int retryTimes() default 5;
}

二·装配分布式锁的bean
@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)public class DistributedLockAutoConfiguration {    @Bean    @ConditionalOnBean(RedisTemplate.class)    public DistributedLock redisDistributedLock(RedisTemplate redisTemplate){        return new RedisDistributedLock(redisTemplate);    }}

三·定义切面(spring boot配置方式)
@Aspect
@Configuration
@ConditionalOnClass(DistributedLock.class)
@AutoConfigureAfter(DistributedLockAutoConfiguration.class)
public class DistributedLockAspectConfiguration {

    private final Logger logger = LoggerFactory.getLogger(DistributedLockAspectConfiguration.class);

    @Autowired
    private DistributedLock distributedLock;

    @Pointcut("@annotation(com.itopener.lock.redis.spring.boot.autoconfigure.annotations.RedisLock)")
    private void lockPoint(){

    }

    @Around("lockPoint()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        RedisLock redisLock = method.getAnnotation(RedisLock.class);
        String key = redisLock.value();
        if(StringUtils.isEmpty(key)){
            Object[] args = pjp.getArgs();
            key = Arrays.toString(args);
        }
        int retryTimes = redisLock.action().equals(LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0;
        boolean lock = distributedLock.lock(key, redisLock.keepMills(), retryTimes, redisLock.sleepMills());
        if(!lock) {
            logger.debug("get lock failed : " + key);
            return null;
        }

        //得到锁,执行方法,释放锁
        logger.debug("get lock success : " + key);
        try {
            return pjp.proceed();
        } catch (Exception e) {
            logger.error("execute locked method occured an exception", e);
        } finally {
            boolean releaseResult = distributedLock.releaseLock(key);
            logger.debug("release lock : " + key + (releaseResult ? " success" : " failed"));
        }
        return null;
    }
}

你可能感兴趣的:(springboot)