技术实现
- redission: Redis官方推荐的Java版的Redis客户端
- aop: 面向切面编程
1. 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.0</version>
</dependency>
2. 配置RedissonClient
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://ip:port");
config.useSingleServer().setPassword("password");
return Redisson.create(config);
}
}
3. 定义锁注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLock {
String key();
long timeout() default 0;
long waitTime() default 1000L;
}
- key: 当前锁的名称
- timeout: 锁的超时时间
- waitTime: 锁的等待时间
4. 解析注解
@Aspect
@Component
public class RedisLockAspect {
private Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);
private static final String PREFIX = "lock:";
@Autowired
private RedissonClient redissonClient;
@Pointcut("@annotation(com.example.demo.annotation.RedisLock)")
public void pointcut(){};
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
RedisLock readLock = signature.getMethod().getAnnotation(RedisLock.class);
String name = PREFIX + readLock.key();
RLock lock = redissonClient.getLock(name);
boolean lockRes;
if (readLock.timeout() == 0) {
lockRes = lock.tryLock(readLock.waitTime(), TimeUnit.MILLISECONDS);
} else {
lockRes = lock.tryLock(readLock.waitTime(), readLock.timeout(), TimeUnit.MILLISECONDS);
}
if (lockRes) {
try {
logger.info("获取redisLock锁成功. name: {}, waitTime: {}, timeout: {}", name, readLock.waitTime(), readLock.timeout());
return pjp.proceed();
} finally {
lock.unlock();
logger.info("释放redisLock锁. name: {}", name);
}
}
throw new RuntimeException("操作正在处理中...");
}
}