Java中通过自定义注解@DistributedLock结合Spring AOP与Redisson实现方法级分布式锁,支持SpEL动态key、超时控制及自动加解锁;需配置RedissonClient,避免事务内使用,确保key唯一可预测。

Java中通过自定义注解实现方法级分布式锁的自动加锁与解锁,核心在于结合Spring AOP拦截目标方法、利用Redis(如Redisson)实现分布式锁逻辑,并在切面中统一处理加锁与释放。
定义自定义注解
声明一个用于标记需要分布式锁的方法的注解,支持配置锁的key、超时时间、等待时间等参数:
(注意:注解必须保留到运行时,且仅适用于方法)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DistributedLock {
String key() default ""; // 锁的key表达式,支持SpEL
long waitTime() default 3; // 获取锁最大等待秒数
long leaseTime() default 10; // 锁持有时间(秒)
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
编写AOP切面实现自动加锁/解锁
使用@Around环绕通知,在方法执行前尝试获取锁,成功后才执行业务逻辑;方法结束后(无论是否异常)主动释放锁:
立即学习“Java免费学习笔记(深入)”;
- 解析注解中的
key(),用ExpressionParser配合StandardEvaluationContext支持SpEL(如"#user.id") - 使用Redisson的
RLock实现可重入、自动续期的分布式锁 - 加锁失败时抛出
LockAcquireException或返回默认值,避免阻塞线程池 - 确保
unlock()放在finally块中,防止因异常导致锁未释放
集成Redisson客户端
引入Redisson依赖并配置单例RedissonClient Bean:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.3</version>
</dependency>
在application.yml中配置Redis地址,Spring Boot会自动装配RedissonClient。切面中直接注入使用即可。
使用示例与注意事项
在Service方法上添加注解,key建议包含业务标识和关键参数:
@Service
public class OrderService {
@DistributedLock(key = "'order:pay:' + #orderId", waitTime = 5, leaseTime = 30)
public void pay(Long orderId) {
// 扣库存、更新订单状态等操作
}
}
- 避免在事务方法内使用该锁(可能引发死锁或锁失效),优先将锁控制在事务外层
- key务必唯一且可预测,禁止使用随机值或未绑定参数的静态字符串
- 不建议在高并发短耗时场景过度使用,需权衡锁开销与数据一致性要求
- 测试时模拟锁冲突(如并发调用同一key方法),验证是否正确阻塞或降级


















