Java分布式锁组件通过自定义注解@DistributedLock+AOP切面+Redisson等客户端实现方法级加锁,支持SpEL动态key、超时等待、可重入、公平锁及异常安全释放,并增强灰度控制、日志追踪与监控指标。

Java 注解可以在分布式锁组件中实现方法级加锁控制,核心思路是:定义自定义注解 + AOP 拦截 + 分布式锁客户端(如 Redisson、RedisTemplate 或 ZooKeeper 客户端)集成。关键不在于“写个注解”,而在于让注解真正触发锁的获取、业务执行、释放全流程,并保障异常安全、可重入、超时自动释放等生产级能力。
定义可配置的锁注解
注解需支持常见控制参数,例如锁名(支持 SpEL 表达式)、过期时间、等待时间、是否可重入等:
-
@DistributedLock 是典型命名,用
@Target({ElementType.METHOD})和@Retention(RetentionPolicy.RUNTIME) - 用
String key() default ""指定锁键,支持#id、#user.name等 SpEL,便于动态生成唯一锁资源 - 添加
long waitTime() default 3000(毫秒)和long leaseTime() default 10000,对应获取锁最大等待时间和锁持有超时时间 - 可选
boolean fair() default false控制是否启用公平锁(取决于底层实现支持)
用 AOP 实现切面逻辑
编写一个 @Aspect 切面,拦截标注了 @DistributedLock 的方法,完成锁生命周期管理:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 在
@Around中解析注解属性,通过EvaluationContext+StandardEvaluationContext计算 SpEL 表达式得到真实 lockKey - 调用分布式锁客户端(如 RedissonClient.getLock(key))获取锁实例
- 尝试
tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS),失败则抛出LockAcquireException或返回默认值 - 成功后执行
proceed(),并在finally块中主动 unlock(注意:仅在当前线程成功加锁后才释放,避免误删他人锁) - 若方法抛异常,锁仍会被正常释放——这是 AOP 保证的 finally 可靠性优势
集成可靠的分布式锁客户端
推荐优先使用 Redisson,它原生支持可重入、看门狗自动续期、红锁、联锁等高级特性,且提供 RLock 接口与 AOP 天然契合:
立即学习“Java免费学习笔记(深入)”;
- Spring Boot 项目引入
redisson-spring-boot-starter,配置好 Redis 地址即可自动装配RedissonClient - 避免手写 SETNX + Lua 脚本方案——易出错、难维护、缺少续期机制,生产环境风险高
- 若必须用原生 RedisTemplate,至少封装原子加锁脚本(含 NX、PX、随机 value 防误删),并自行实现心跳续期线程池
- ZooKeeper 方案(如 Curator 的 InterProcessMutex)适合强一致性场景,但性能和运维成本高于 Redis
增强实用性与可观测性
生产环境中还需补充几个细节,才能称得上“优雅”:
- 支持
@DistributedLock(enabled = "#featureFlag")条件启用,方便灰度或降级 - 记录加锁耗时、是否抢锁成功、锁 key 等日志(INFO 或 DEBUG 级),配合 traceId 排查问题
- 暴露 Actuator 端点,统计当前持有锁数量、平均等待时间等指标(可用 Micrometer + Prometheus)
- 对读多写少场景,可扩展为读写锁注解(
@DistributedReadWriteLock),区分RLock和RReadWriteLock

















