package com.xtc.supplier.datacenter.service;
/**
* @author zhou yang yang
* @since 2022/6/10 9:38
*/
public interface LockService {
/**
* 是否上锁
*
* @return true 已上锁
*/
boolean isLocked(String key);
/**
* 加锁
*/
void lock(String key);
/**
* 加锁
*/
void lock(String key, Runnable runnable);
/**
* 执行runnable, 如果出现异常则解锁,并且抛出。
*/
void runnable(String key, Runnable runnable);
/**
* 解锁
*/
void unlock(String key);
/**
* 生成key值
*
* @return key = 当前方法引用+identifier
*/
default String key(StackTraceElement stackTraceElement, String identifier) {
return String.format("%s#%s()_%s", stackTraceElement.getClassName(), stackTraceElement.getMethodName(), identifier);
}
}
package com.xtc.supplier.datacenter.service.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xtc.supplier.datacenter.mapper.LockMapper;
import com.xtc.supplier.datacenter.pojo.entity.LockDO;
import com.xtc.supplier.datacenter.service.LockService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* 分布式锁,key = 当前方法引用+供应商代码。
* stackTraceElement 使用方法:StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[1];
*
* @author zhou yang yang
* @since 2022/6/10 9:41
*/
@Service
@RequiredArgsConstructor
public class LockServiceImpl extends ServiceImpl<LockMapper, LockDO> implements LockService {
/**
* 是否上锁
* 1. 如果存在数据,则表示已经上锁。
*
* @return true 已上锁
*/
@Override
public boolean isLocked(String key) {
return Objects.nonNull(getById(key));
}
/**
* 加锁,添加数据。
*/
@Override
public void lock(String key) {
save(new LockDO(key));
}
/**
* 加锁,添加数据。
* runnable 需要执行的数据,如果run出现异常则进行解锁
*/
@Override
public void lock(String key, Runnable runnable) {
lock(key);
runnable(key, runnable);
}
/**
* 执行runnable, 如果出现异常则解锁,并且抛出。
*/
@Override
public void runnable(String key, Runnable runnable) {
try {
runnable.run();
} catch (Exception exception) {
unlock(key);
throw new RuntimeException(exception);
}
}
/**
* 解锁,删除当前锁。
*/
@Override
public void unlock(String key) {
removeById(key);
}
}