package com.kwan.springbootkwan.aop; import com.kwan.springbootkwan.annotation.RedisLock; import com.kwan.springbootkwan.schedule.RedisLockRenewal; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; 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; @Autowired private RedisLockRenewal redisLockRenewal; 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); redisLockRenewal.scheduleRenewal(lockKey, 20000, redisLock.expire()); } 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; } }