RedisLockAspect.java 2.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
package com.kwan.springbootkwan.aop;

import com.kwan.springbootkwan.annotation.RedisLock;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


@Aspect
@Component
@Order(1)  // 设置切面优先级
public class RedisLockAspect {

    private final StringRedisTemplate redisTemplate;

    public RedisLockAspect(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Around("@annotation(redisLock)")
    public Object doWithLock(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
        String lockKey = getLockKey(redisLock);
        Lock lock = new ReentrantLock(redisLock.fair());
        boolean locked = false;

        try {
            locked = lock.tryLock(redisLock.timeout(), TimeUnit.MILLISECONDS);
            if (locked) {
                if (StringUtils.hasText(lockKey)) {
                    redisTemplate.opsForValue().set(lockKey, "locked", redisLock.expire(), TimeUnit.MILLISECONDS);
                }
                return joinPoint.proceed();
            } else {
                throw new RuntimeException("Failed to acquire lock.");
            }
        } finally {
            if (locked) {
                lock.unlock();
                if (StringUtils.hasText(lockKey)) {
                    redisTemplate.delete(lockKey);
                }
            }
        }
    }

    private String getLockKey(RedisLock redisLock) {
        String lockKey = redisLock.key();
        if (!StringUtils.hasText(lockKey)) {
            lockKey = redisLock.name();
        }
        return lockKey;
    }
}