1、手动加解锁
官方README上的手动上锁代码如下:
@Service
public class ProgrammaticService {
@Autowired
private LockTemplate lockTemplate;
public void programmaticLock(String userId) {
// 各种查询操作 不上锁
// ...
// 尝试获取锁
final LockInfo lockInfo = lockTemplate.lock(userId, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
// 获取锁失败
throw new RuntimeException("业务处理中,请稍后再试");
}
// 获取锁成功,处理业务
try {
System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName() + " , counter:" + (counter++));
} finally {
//释放锁
lockTemplate.releaseLock(lockInfo);
}
//结束
}
}
复制代码
- 整体清晰易懂,主要就是通过LockTemplate这个类获取锁。如果获取锁成功,则进行业务处理,此时其他线程获取锁会失败。如果获取锁失败,则表示其他线程正在处理业务,当前线程阻塞等待。
- 重点在LockTemplate上,从代码中发现是自动注入了,因此我们很容易想到,Lock4j框架应该使用了Springboot的自动注入能力,即我们是能够在代码中找到xxxAutoConfiguration.java这个类,该类将LockTemplate注入到了Spring容器中。
接下来我们便来看看这个xxxAutoConfiguration吧。
2、自动注入
自动注入的代码如下所示:
// LockAutoConfiguration.java
@Configuration
// 激活Lock4jProperties配置,用户的 lock4j.xxx 的配置可以注解注入到当前Lock4jProperties属性中
@EnableConfigurationProperties(Lock4jProperties.class)
@RequiredArgsConstructor
public class LockAutoConfiguration {
private final Lock4jProperties properties;
@SuppressWarnings("rawtypes")
@Bean
@ConditionalOnMissingBean
// 自动注入 LockTemplate 对象
// LockExecutor是分布式锁核心处理器,这里通过引入不同框架(RedisTemplate、Redisson、zk)使用不同的分布式锁能力
public LockTemplate lockTemplate(List<LockExecutor> executors) {
LockTemplate lockTemplate = new LockTemplate();
lockTemplate.setProperties(properties);
lockTemplate.setExecutors(executors);
return lockTemplate;
}
@Bean
@ConditionalOnMissingBean
// 自动注入 LockKeyBuilder 对象,用于构造分布式锁的key
public LockKeyBuilder lockKeyBuilder() {
return new DefaultLockKeyBuilder();
}
@Bean
@ConditionalOnMissingBean
// 自动注入 DefaultLockFailureStrategy 对象,获取锁失败的处理策略
public LockFailureStrategy lockFailureStrategy() {
re