Commit 16a8bf92 authored by lijun's avatar lijun

del lock model

parent 097828a9
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
<module>smart-common-sequence</module> <module>smart-common-sequence</module>
<module>smart-common-swagger</module> <module>smart-common-swagger</module>
<module>smart-common-im</module> <module>smart-common-im</module>
<module>smart-common-lock</module>
<module>smart-common-mq</module> <module>smart-common-mq</module>
</modules> </modules>
</project> </project>
...@@ -96,11 +96,6 @@ ...@@ -96,11 +96,6 @@
<artifactId>smart-common-im</artifactId> <artifactId>smart-common-im</artifactId>
<version>${smart.version}</version> <version>${smart.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-common-lock</artifactId>
<version>${smart.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.smart.hospital</groupId> <groupId>com.smart.hospital</groupId>
<artifactId>smart-common-mq</artifactId> <artifactId>smart-common-mq</artifactId>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-hospital-common</artifactId>
<version>3.3.0</version>
</parent>
<artifactId>smart-common-lock</artifactId>
<packaging>jar</packaging>
<description>分布式锁(自定义Advisor)</description>
<properties>
<redisson.version>3.16.1</redisson.version>
<zookeeper.version>4.2.0</zookeeper.version>
</properties>
<dependencies>
<dependency>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-common-core</artifactId>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${zookeeper.version}</version>
</dependency>
</dependencies>
</project>
package com.smart.hospital.common.lock;
import com.smart.hospital.common.lock.advisor.LockInterceptorAutoConfiguration;
import com.smart.hospital.common.lock.config.InitConfig;
import com.smart.hospital.common.lock.config.ZkRetryPolicyStore;
import com.smart.hospital.common.lock.config.ZookeeperSchemeConfig;
import com.smart.hospital.common.lock.config.zookeeper.ExponentialBackoffRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.ForeverRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.NTimesRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.UntilElapsedRetryConfig;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.custom.PropertiesCustomizer;
import com.smart.hospital.common.lock.custom.impl.CodecPropertiesCustomizer;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.ZkRetryPolicy;
import com.smart.hospital.common.lock.properties.LockProperties;
import com.smart.hospital.common.lock.provider.manager.PatternManager;
import com.smart.hospital.common.lock.provider.manager.RedisServerPatternManager;
import com.smart.hospital.common.lock.provider.pattern.PatternProvider;
import com.smart.hospital.common.lock.provider.pattern.RedisClusterProvider;
import com.smart.hospital.common.lock.provider.pattern.RedisSingleProvider;
import com.smart.hospital.common.lock.service.LockProviderManager;
import com.smart.hospital.common.lock.service.LockServiceManager;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import com.smart.hospital.common.lock.service.provider.redis.RedisFairLockServiceProvider;
import com.smart.hospital.common.lock.service.provider.redis.RedisMultiLockServiceProvider;
import com.smart.hospital.common.lock.service.provider.redis.RedisReentrantLockServiceProvider;
import com.smart.hospital.common.lock.service.provider.zookeeper.ZookeeperMultiZkLockServiceProvider;
import lombok.SneakyThrows;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryForever;
import org.apache.curator.retry.RetryNTimes;
import org.apache.curator.retry.RetryUntilElapsed;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* 分布式锁自动配置类
*/
@Configuration
@EnableConfigurationProperties(LockProperties.class)
@Import({LockInterceptorAutoConfiguration.class, CodecPropertiesCustomizer.class})
public class LockAutoConfiguration {
private final List<PropertiesCustomizer> customizers;
public LockAutoConfiguration(ObjectProvider<List<PropertiesCustomizer>> objectCustomizers) {
this.customizers = objectCustomizers.getIfAvailable();
}
@Bean(LockCommonConstant.LOCK_CLIENT_BEAN_NAME)
@ConditionalOnMissingBean(name = {LockCommonConstant.LOCK_CLIENT_BEAN_NAME})
@ConditionalOnProperty(prefix = LockProperties.LOCK_PREFIX, name = LockProperties.PROPERTY_NAME, havingValue = LockScheme.LockSchemeConstant.REDIS)
public RedissonClient redissonClient(PatternManager patternManager, LockProperties lockProperties) {
// 对lockProperties进行自定义配置
applyProperties(lockProperties);
// 构造redisson配置
InitConfig initConfig = new InitConfig(lockProperties.getPattern(), lockProperties, lockProperties.getCodec());
return patternManager.initConfig(initConfig);
}
private void applyProperties(LockProperties lockProperties) {
if (!CollectionUtils.isEmpty(this.customizers)) {
for (PropertiesCustomizer customizer : this.customizers) {
customizer.customize(lockProperties);
}
}
}
/* Lock Pattern configuration : 锁类型的初始化配置(单机,集群等) */
@Bean
public PatternManager patternManager(ObjectProvider<List<PatternProvider>> objectProviders) {
return new RedisServerPatternManager(objectProviders.getIfAvailable());
}
/**
* redis单机模式配置
*
* @return
*/
@Bean
public PatternProvider redisSingleProvider() {
return new RedisSingleProvider();
}
/**
* redis集群模式配置
*
* @return
*/
@Bean
public PatternProvider redisClusterProvider() {
return new RedisClusterProvider();
}
/* zookeeper 客户端配置 */
@Bean(LockCommonConstant.LOCK_CLIENT_BEAN_NAME)
@ConditionalOnMissingBean(name = {LockCommonConstant.LOCK_CLIENT_BEAN_NAME})
@ConditionalOnProperty(prefix = LockProperties.LOCK_PREFIX, name = LockProperties.PROPERTY_NAME, havingValue = LockScheme.LockSchemeConstant.ZOOKEEPER)
public CuratorFramework zkClient(LockProperties lockProperties) {
ZookeeperSchemeConfig zookeeperSchemeConfig = lockProperties.getZookeeper();
CuratorFramework curatorClient = CuratorFrameworkFactory.newClient(zookeeperSchemeConfig.getAddress(),
zookeeperSchemeConfig.getSessionTimeout(), zookeeperSchemeConfig.getConnectionTimeoutMs(),
initZkRetryPolicy(zookeeperSchemeConfig));
curatorClient.start();
return curatorClient;
}
/**
* 初始化zk重试策略
*
* @param zookeeperSchemeConfig
* @return
*/
@SneakyThrows
private RetryPolicy initZkRetryPolicy(ZookeeperSchemeConfig zookeeperSchemeConfig) {
ZkRetryPolicy zkRetryPolicy = ZkRetryPolicyStore.getPolicy(zookeeperSchemeConfig.getRetryPolicy());
if (zkRetryPolicy == ZkRetryPolicy.RETRY_EXPONENTIAL_BACKOFF) {
ExponentialBackoffRetryConfig exponentialBackoffRetryConfig = zookeeperSchemeConfig
.getExponentialBackoffRetry();
return new ExponentialBackoffRetry(exponentialBackoffRetryConfig.getBaseSleepTimeMs(),
exponentialBackoffRetryConfig.getMaxRetries(), exponentialBackoffRetryConfig.getMaxSleepMs());
}
if (zkRetryPolicy == ZkRetryPolicy.RETRY_FOREVER) {
ForeverRetryConfig foreverRetryConfig = zookeeperSchemeConfig.getForeverRetry();
return new RetryForever(foreverRetryConfig.getRetryIntervalMs());
}
if (zkRetryPolicy == ZkRetryPolicy.RETRY_NTIMES) {
NTimesRetryConfig ntimesRetryConfig = zookeeperSchemeConfig.getNtimesRetry();
return new RetryNTimes(ntimesRetryConfig.getN(), ntimesRetryConfig.getSleepMsBetweenRetries());
}
if (zkRetryPolicy == ZkRetryPolicy.RETRY_UNTIL_ELAPSED) {
UntilElapsedRetryConfig untilElapsedRetryConfig = zookeeperSchemeConfig.getUntilElapsedRetry();
return new RetryUntilElapsed(untilElapsedRetryConfig.getMaxElapsedTimeMs(),
untilElapsedRetryConfig.getSleepMsBetweenRetries());
}
return null;
}
/* lock service configuration : 锁操作客户端的类型配置(zk/redis等 重入/红锁等) */
@Bean
@ConditionalOnClass(RedissonClient.class)
public LockServiceManager lockServiceManager(ObjectProvider<List<LockServiceProvider>> lockServiceProviders, @Nullable RedissonClient redissonClient, @Nullable CuratorFramework zkClient) {
return new LockProviderManager(lockServiceProviders.getIfAvailable(), redissonClient, zkClient);
}
/**
* redis可重入锁
*
* @return
*/
@Bean
public LockServiceProvider redisReentrantLockServiceProvider() {
return new RedisReentrantLockServiceProvider();
}
/**
* redis公平锁
*
* @return
*/
@Bean
public LockServiceProvider redisFairLockServiceProvider() {
return new RedisFairLockServiceProvider();
}
/**
* redis联锁
*
* @return
*/
@Bean
public LockServiceProvider redisMultiLockServiceProvider() {
return new RedisMultiLockServiceProvider();
}
/**
* zookeeper联锁
*
* @return
*/
@Bean
public LockServiceProvider zookeeperMultiZkLockServiceProvider() {
return new ZookeeperMultiZkLockServiceProvider();
}
}
package com.smart.hospital.common.lock.advisor;
import com.smart.hospital.common.lock.advisor.pointcut.DistributedLockPointcut;
import com.smart.hospital.common.lock.advisor.source.LockAttributeSource;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.lang.Nullable;
/**
* 分布式锁Advisor
*/
public class DistributedLockAdvisor extends AbstractPointcutAdvisor {
private transient volatile Object adviceMonitor = new Object();
@Nullable
private transient volatile Advice advice;
private LockAttributeSource lockAttributeSource;
private final DistributedLockPointcut pointcut = new DistributedLockPointcut() {
@Override
protected LockAttributeSource getLockAttributeSource() {
return lockAttributeSource;
}
};
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
Advice advice = this.advice;
if (advice != null) {
return advice;
}
return null;
}
public void setAdvice(Advice advice) {
synchronized (this.adviceMonitor) {
this.advice = advice;
}
}
public void setLockAttributeSource(LockAttributeSource lockAttributeSource) {
this.lockAttributeSource = lockAttributeSource;
}
}
package com.smart.hospital.common.lock.advisor;
import com.smart.hospital.common.lock.advisor.intercept.LockInterceptor;
import com.smart.hospital.common.lock.advisor.source.AnnotationDistributedLockAttributeSource;
import com.smart.hospital.common.lock.advisor.source.LockAttributeSource;
import com.smart.hospital.common.lock.custom.InterceptorCustomizer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* 创建锁切面自动配置类
*/
@Configuration
public class LockInterceptorAutoConfiguration {
private final List<InterceptorCustomizer> customizers;
public LockInterceptorAutoConfiguration(ObjectProvider<List<InterceptorCustomizer>> customizers) {
this.customizers = customizers.getIfAvailable();
}
/**
* 创建锁的切面
*
* @return
*/
@Bean
public DistributedLockAdvisor distributedLockAdvisor() {
DistributedLockAdvisor advisor = new DistributedLockAdvisor();
advisor.setLockAttributeSource(lockAttributeSource());
advisor.setAdvice(lockInterceptor());
return advisor;
}
/**
* 注解信息解析
*
* @return
*/
@Bean
public LockAttributeSource lockAttributeSource() {
return new AnnotationDistributedLockAttributeSource();
}
/**
* 具体的切面逻辑
*
* @return
*/
@Bean
public LockInterceptor lockInterceptor() {
LockInterceptor interceptor = new LockInterceptor();
interceptor.setLockAttributeSource(lockAttributeSource());
applyLockInterceptor(interceptor);
return interceptor;
}
public void applyLockInterceptor(LockInterceptor interceptor) {
if (!CollectionUtils.isEmpty(this.customizers)) {
for (InterceptorCustomizer customizer : customizers) {
customizer.customize(interceptor);
}
}
}
}
package com.smart.hospital.common.lock.advisor.attribute;
import com.smart.hospital.common.lock.enums.LockType;
import java.util.concurrent.TimeUnit;
public class DistributedLockAttribute implements LockAttribute {
/**
* 锁类型
*/
private LockType lockType;
/**
* 加锁时间,超过该时长自动解锁,默认单位为:秒
*/
private long leaseTime;
/**
* 等待锁时间,默认单位:秒
*/
private long waitTime;
/**
* 锁时长单位
*/
private TimeUnit timeUnit;
@Override
public LockType getLockType() {
return lockType;
}
public void setLockType(LockType lockType) {
this.lockType = lockType;
}
@Override
public long getLeaseTime() {
return leaseTime;
}
public void setLeaseTime(long leaseTime) {
this.leaseTime = leaseTime;
}
@Override
public long getWaitTime() {
return waitTime;
}
public void setWaitTime(long waitTime) {
this.waitTime = waitTime;
}
@Override
public TimeUnit getTimeUnit() {
return timeUnit;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
@Override
public String toString() {
return "DistributedLockAttribute{" +
"lockType=" + lockType +
", leaseTime=" + leaseTime +
", waitTime=" + waitTime +
", timeUnit=" + timeUnit +
'}';
}
}
package com.smart.hospital.common.lock.advisor.attribute;
import com.smart.hospital.common.lock.enums.LockType;
import java.util.concurrent.TimeUnit;
/**
* 锁属性
*/
public interface LockAttribute {
/**
* 获取锁类型
*
* @return
*/
LockType getLockType();
/**
* 加锁时间,超过该时长自动解锁,默认单位为:秒
*
* @return
*/
long getLeaseTime();
/**
* 等待锁时间,默认单位:秒
*
* @return
*/
long getWaitTime();
/**
* 锁时长单位
*
* @return
*/
TimeUnit getTimeUnit();
}
package com.smart.hospital.common.lock.advisor.intercept;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
/**
* 分布式锁增强器
*/
public class LockInterceptor extends LockInterceptorSupport implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
return invocationWithLock(invocation.getMethod(), targetClass, invocation.getArguments(), invocation::proceed);
}
}
package com.smart.hospital.common.lock.advisor.intercept;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.advisor.source.LockAttributeSource;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import com.smart.hospital.common.lock.service.LockServiceManager;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
@Slf4j
public abstract class LockInterceptorSupport implements InitializingBean, ApplicationContextAware {
@Nullable
private ApplicationContext applicationContext;
private LockAttributeSource lockAttributeSource;
private RedissonClient redissonClient;
@Autowired
private LockServiceManager lockServiceManager;
@Nullable
private String redissonClientBeanName = LockCommonConstant.LOCK_CLIENT_BEAN_NAME;
private final ConcurrentMap<Object, RedissonClient> clientCache =
new ConcurrentReferenceHashMap<>(4);
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
if (this.applicationContext == null && getRedissonClient() == null) {
throw new IllegalArgumentException(
"Set the 'redissonClient' property or make sure to run within a BeanFactory " +
"containing a RedissonClient bean!");
}
if (getLockAttributeSource() == null) {
throw new IllegalArgumentException("LockAttributeSource' is required:" + "没用配置资源解析类");
}
}
private RedissonClient determineRedissonClient() {
RedissonClient redissonClient = clientCache.get(this.redissonClientBeanName);
if (redissonClient != null) {
return redissonClient;
}
if (this.applicationContext == null && getRedissonClient() != null) {
return getRedissonClient();
}
RedissonClient bean;
if (StringUtils.hasText(this.redissonClientBeanName)) {
bean = (RedissonClient) applicationContext.getBean(redissonClientBeanName);
} else {
bean = applicationContext.getBean(RedissonClient.class);
}
if (bean == null) {
throw new NoSuchBeanDefinitionException("No matching bean found for bean name : " + this.redissonClientBeanName);
}
this.redissonClient = bean;
clientCache.put(this.redissonClientBeanName, bean);
return bean;
}
protected Object invocationWithLock(Method method, Class<?> targetClass, Object[] arguments, InvocationCallback invocation) throws Throwable {
Object retVal;
LockKey<String, List<String>> lockKey;
LockService lockService = null;
try {
LockAttributeSource as = getLockAttributeSource();
LockAttribute attr = as.getLockAttribute(method, targetClass);
if (attr != null) {
// 在这里解析@Key注解的信息
lockKey = as.getLockKey(method, targetClass, arguments, attr);
if (lockKey != null) {
lockService = lockServiceManager.findLockService(lockKey);
if (lockService != null) {
lockService.lock();
}
}
}
retVal = invocation.proceedWithInvocation();
} finally {
if (lockService != null) {
lockService.release();
}
}
return retVal;
}
@FunctionalInterface
protected interface InvocationCallback {
Object proceedWithInvocation() throws Throwable;
}
public void setRedissonClientBeanName(@Nullable String redissonClientBeanName) {
this.redissonClientBeanName = redissonClientBeanName;
}
public LockAttributeSource getLockAttributeSource() {
return lockAttributeSource;
}
public void setLockAttributeSource(LockAttributeSource lockAttributeSource) {
this.lockAttributeSource = lockAttributeSource;
}
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
public RedissonClient getRedissonClient() {
return this.redissonClient;
}
}
package com.smart.hospital.common.lock.advisor.parser;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.annotation.Lock;
import com.smart.hospital.common.lock.annotation.RLock;
import com.smart.hospital.common.lock.annotation.ZLock;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.strategy.*;
import com.smart.hospital.common.lock.key.strategy.impl.ClassKeyStrategy;
import com.smart.hospital.common.lock.key.strategy.impl.FieldKeyStrategy;
import com.smart.hospital.common.lock.key.strategy.impl.MethodKeyStrategy;
import com.smart.hospital.common.lock.key.strategy.impl.ParameterKeyStrategy;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationAttributes;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public abstract class AbstractLockAnnotationParser implements LockAnnotationParser {
/**
* 所有的所注解类型
*/
private static final Class<? extends Annotation>[] LOCK_ANNOTATION_CLASSES = new Class[]{Lock.class, RLock.class, ZLock.class};
/**
* 所有作为key的标记的注解 目前用@Key
*/
private static final Class<? extends Annotation> KEY_ANNOTATION_CLASS = KeyStrategy.KEY_ANNOTATION_CLASS;
@Override
public LockAttribute parseLockAnnotation(AnnotatedElement element) {
// 找到注解信息
for (Class<? extends Annotation> clazz : LOCK_ANNOTATION_CLASSES) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, clazz, false, false);
if (attributes != null) {
return parseLockAnnotation(attributes);
}
}
return null;
}
@Override
public KeyStrategy parseKeyAnnotation(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr) {
return getKeyStrategyFromMethod(method, targetClass, arguments, attr);
}
@Override
public LockScheme getLockScheme(Method realMethod) {
if (null != realMethod.getAnnotation(Lock.class) || null != realMethod.getAnnotation(RLock.class)) {
return LockScheme.REDIS;
}
return LockScheme.ZOOKEEPER;
}
private KeyStrategy getKeyStrategyFromMethod(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr) {
LockScheme scheme = getLockScheme(method);
// 参数锁
Parameter[] parameters = method.getParameters();
if (parameters != null && parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].isAnnotationPresent(KEY_ANNOTATION_CLASS)) {
return new ParameterKeyStrategy(targetClass.getName(), method.getName(), method, arguments, scheme, attr);
}
}
}
// 方法锁
if (null != method.getAnnotation(KEY_ANNOTATION_CLASS)) {
return new MethodKeyStrategy(targetClass.getName(), method.getName(), method, arguments, scheme, attr);
}
// 属性锁
if (arguments != null && arguments.length > 0) {
for (int i = 0; i < arguments.length; i++) {
Object argument = arguments[i];
if (argument == null) {
continue;
}
Class<?> argumentClass = argument.getClass();
Field[] fields = argumentClass.getDeclaredFields();
for (Field field : fields) {
if (null != field.getAnnotation(KEY_ANNOTATION_CLASS)) {
return new FieldKeyStrategy(targetClass.getName(), method.getName(), method, arguments, scheme, attr);
}
}
}
}
// 类名和方法名作为key的锁
return new ClassKeyStrategy(targetClass.getName(), method.getName(), method, arguments, scheme, attr);
}
protected abstract LockAttribute parseLockAnnotation(AnnotationAttributes attributes);
protected abstract LockAttribute parseLockAnnotation(Annotation annotation);
}
package com.smart.hospital.common.lock.advisor.parser;
import com.smart.hospital.common.lock.advisor.attribute.DistributedLockAttribute;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.enums.LockType;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.util.concurrent.TimeUnit;
/**
* 分布式锁注解解析类
*/
public class DistributedLockAnnotationParser extends AbstractLockAnnotationParser {
@Override
protected LockAttribute parseLockAnnotation(AnnotationAttributes attributes) {
DistributedLockAttribute attr = new DistributedLockAttribute();
// 锁类型
if (attributes.containsKey("lockType")) {
LockType lockType = attributes.getEnum("lockType");
attr.setLockType(lockType);
}
// 加锁时间
if (attributes.containsKey("leaseTime")) {
attr.setLeaseTime(attributes.getNumber("leaseTime"));
}
// 等待时间
if (attributes.containsKey("waitTime")) {
attr.setWaitTime(attributes.getNumber("waitTime"));
}
// 时间单位
if (attributes.containsKey("timeUnit")) {
TimeUnit timeUnit = attributes.getEnum("timeUnit");
attr.setTimeUnit(timeUnit);
}
return attr;
}
@Override
protected LockAttribute parseLockAnnotation(Annotation annotation) {
return parseLockAnnotation(AnnotationUtils.getAnnotationAttributes(annotation, false, false));
}
}
package com.smart.hospital.common.lock.advisor.parser;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.strategy.KeyStrategy;
import java.lang.reflect.Method;
/**
* @Key解析类
*/
public interface KeyAnnotationParser {
/**
* 从方法获取@Key注解信息
*
* @param method
* @return
*/
KeyStrategy parseKeyAnnotation(Method method, Class<?> targetClass, Object[] arguments);
/**
* 获取锁类型 事zookeeper还是redis
*
* @param realMethod
* @return
*/
LockScheme getLockScheme(Method realMethod);
}
package com.smart.hospital.common.lock.advisor.parser;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.strategy.KeyStrategy;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
/**
* 分布式锁注解解析器
*/
public interface LockAnnotationParser {
/**
* 解析指定方法或则类的注解信息
*
* @param element
* @return
*/
LockAttribute parseLockAnnotation(AnnotatedElement element);
/**
* 从方法获取@Key注解信息
*
* @param method
* @return
*/
KeyStrategy parseKeyAnnotation(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr);
/**
* 获取锁类型 事zookeeper还是redis
*
* @param realMethod
* @return
*/
LockScheme getLockScheme(Method realMethod);
}
package com.smart.hospital.common.lock.advisor.pointcut;
import com.smart.hospital.common.lock.advisor.source.LockAttributeSource;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import java.lang.reflect.Method;
public abstract class DistributedLockPointcut implements MethodMatcher, Pointcut {
private ClassFilter classFilter = ClassFilter.TRUE;
@Override
public boolean matches(Method method, Class<?> targetClass) {
LockAttributeSource tas = getLockAttributeSource();
return (tas == null || tas.getLockAttribute(method, targetClass) != null);
}
@Override
public boolean isRuntime() {
return false;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// should never be invoked because isRuntime() returns false
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
}
@Override
public ClassFilter getClassFilter() {
return this.classFilter;
}
public void setClassFilter(ClassFilter classFilter) {
this.classFilter = classFilter;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
protected abstract LockAttributeSource getLockAttributeSource();
}
package com.smart.hospital.common.lock.advisor.source;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.key.LockKey;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.MethodClassKey;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractDistributedLockAttributeSource implements LockAttributeSource {
/**
* @Lock注解属性的缓存
*/
private final Map<Object, LockAttribute> attributeCache = new ConcurrentHashMap<>(16);
/**
* 锁的操作对象缓存
*/
private final Map<Object, LockKey<String, List<String>>> lockServiceCache = new ConcurrentHashMap<>(16);
@Override
public LockAttribute getLockAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// 先从本地缓存中取
Object cacheKey = getCacheKey(method, targetClass);
LockAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
return cached;
}
// 解析注解信息
LockAttribute attr = computeLockAttribute(method, targetClass);
if (attr != null) {
// 将信息放入本地缓存
this.attributeCache.put(cacheKey, attr);
}
return attr;
}
@Override
public LockKey<String, List<String>> getLockKey(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
Object cacheKey = getCacheKey(method, targetClass);
LockKey<String, List<String>> cached = this.lockServiceCache.get(cacheKey);
if (cached != null) {
return cached;
}
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
LockKey<String, List<String>> lockKey = findLockKey(specificMethod, targetClass, arguments, attr);
if (lockKey != null) {
return lockKey;
}
return null;
}
protected LockAttribute computeLockAttribute(Method method, Class<?> targetClass) {
// 只允许public公共方法 并且 方法不是公共方法 = 不是公共方法匹配失败
if (allowPublicMethodOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 从代理对象上的一个方法,找到真实对象上对应的方法。
// 举个例子,MyComponent代理之后的对象上的someLogic方法,肯定是属于cglib代理之后的类上的method,
// 使用这个method是没法去执行目标MyComponent的someLogic方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class
LockAttribute attr = findLockAttribute(specificMethod);
if (attr != null) {
return attr;
}
// Second try is the lock attribute on the target class.
attr = findLockAttribute(targetClass);
if (attr != null && ClassUtils.isUserLevelMethod(method)) {
return attr;
}
if (specificMethod != method) {
attr = findLockAttribute(method);
if (attr != null) {
return attr;
}
attr = findLockAttribute(method.getDeclaringClass());
if (attr != null && ClassUtils.isUserLevelMethod(method)) {
return attr;
}
}
return null;
}
/**
* 从方法解析@Lock注解信息
*
* @param method
* @return
*/
protected abstract LockAttribute findLockAttribute(Method method);
/**
* 从类解析@Lock注解信息
*
* @param clazz
* @return
*/
protected abstract LockAttribute findLockAttribute(Class<?> clazz);
/**
* 从方法上获取注解信息
*
* @param method
* @return
*/
protected abstract LockKey<String, List<String>> findLockKey(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr);
/**
* 只匹配public的方法创建代理
*
* @return
*/
protected boolean allowPublicMethodOnly() {
return false;
}
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
}
}
package com.smart.hospital.common.lock.advisor.source;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.advisor.parser.DistributedLockAnnotationParser;
import com.smart.hospital.common.lock.advisor.parser.LockAnnotationParser;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.strategy.KeyStrategy;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* 注解解析资源
*/
public class AnnotationDistributedLockAttributeSource extends AbstractDistributedLockAttributeSource {
/**
* 只允许解析public修饰的方法
*/
private final boolean publicMethodsOnly;
/**
* 委托的注解解析器
*/
private final Set<LockAnnotationParser> annotationParsers;
public AnnotationDistributedLockAttributeSource() {
this(true);
}
public AnnotationDistributedLockAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = Collections.singleton(new DistributedLockAnnotationParser());
}
@Override
protected LockAttribute findLockAttribute(Method method) {
return determineLockAttribute(method);
}
@Override
protected LockAttribute findLockAttribute(Class<?> clazz) {
return determineLockAttribute(clazz);
}
protected LockAttribute determineLockAttribute(AnnotatedElement element) {
for (LockAnnotationParser parser : this.annotationParsers) {
LockAttribute attr = parser.parseLockAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
@Override
protected LockKey<String, List<String>> findLockKey(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr) {
KeyStrategy strategy = null;
for (LockAnnotationParser parser : this.annotationParsers) {
strategy = parser.parseKeyAnnotation(method, targetClass, arguments, attr);
if (strategy != null) {
break;
}
}
if (strategy != null) {
return strategy.buildKey();
}
return null;
}
@Override
protected boolean allowPublicMethodOnly() {
return this.publicMethodsOnly;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AnnotationDistributedLockAttributeSource)) {
return false;
}
AnnotationDistributedLockAttributeSource otherTas = (AnnotationDistributedLockAttributeSource) other;
return (this.annotationParsers.equals(otherTas.annotationParsers) &&
this.publicMethodsOnly == otherTas.publicMethodsOnly);
}
@Override
public int hashCode() {
return Objects.hash(annotationParsers);
}
}
package com.smart.hospital.common.lock.advisor.source;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.key.LockKey;
import java.lang.reflect.Method;
import java.util.List;
public interface LockAttributeSource {
/**
* 从方法或者类上面通过反射获取注解信息
* 在拦截器(拦截方法获取注解信息)和切点(判断是否创建切面代理)解析的时候会用到
*
* @param method
* @param targetClass
* @return
*/
LockAttribute getLockAttribute(Method method, Class<?> targetClass);
/**
* 从方法上的注解@Key
*
* @param method
* @param targetClass
* @param arguments
* @return
*/
LockKey<String, List<String>> getLockKey(Method method, Class<?> targetClass, Object[] arguments, LockAttribute attr);
}
package com.smart.hospital.common.lock.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于分布式锁的key
*/
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Key {
String[] value() default {};
}
package com.smart.hospital.common.lock.annotation;
import com.smart.hospital.common.lock.enums.LockType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* 锁的注解 (使用Redis作为分布式锁)
* @author TanRq
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
public @interface Lock {
/**
* 锁类型
* @return
*/
LockType lockType() default LockType.REENTRANT;
/**
* 加锁时间,超过该时长自动解锁,默认单位为:秒
* @return
*/
long leaseTime() default -1;
/**
* 等待锁时间,默认单位:秒
* @return
*/
long waitTime() default -1;
/**
* 锁时长单位
* @return
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
package com.smart.hospital.common.lock.annotation;
import com.smart.hospital.common.lock.enums.LockType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* @author TanRq
* @date 2020年4月28日 上午10:01:46
* @description Redis分布式锁的注解,同 @Lock
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
public @interface RLock {
/**
* 锁类型
* @return
*/
LockType lockType() default LockType.REENTRANT;
/**
* 加锁时间,超过该时长自动解锁,默认单位为:秒
* @return
*/
long leaseTime() default -1;
/**
* 等待锁时间,默认单位:秒
* @return
*/
long waitTime() default -1;
/**
* 锁时长单位
* @return
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
package com.smart.hospital.common.lock.annotation;
import com.smart.hospital.common.lock.enums.LockType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* zookeeper分布式锁的注解
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
public @interface ZLock {
/**
* 锁类型
*
* @return
*/
LockType lockType() default LockType.MUTEX;
/**
* 等待锁时间,默认单位:秒
*
* @return
*/
long waitTime() default 1;
/**
* 锁时长单位
*
* @return
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
package com.smart.hospital.common.lock.config;
import com.smart.hospital.common.lock.properties.LockProperties;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
public class InitConfig extends Config {
/**
* 默认是redis的单机模式
*/
private final String pattern;
/**
* 配置信息
*/
private final LockProperties lockProperties;
public String getPattern() {
return pattern;
}
public LockProperties getLockProperties() {
return lockProperties;
}
public InitConfig(String pattern, LockProperties lockProperties, Codec codec) {
this.pattern = pattern;
this.lockProperties = lockProperties;
if (codec != null) {
this.setCodec(codec);
}
}
}
package com.smart.hospital.common.lock.config;
import com.smart.hospital.common.lock.config.redis.RedisClusterConfig;
import com.smart.hospital.common.lock.config.redis.RedisSingleConfig;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
/**
* redis配置
*/
public class RedisSchemeConfig {
/**
* 单机模式配置
*/
private RedisSingleConfig singleServer;
/**
* redis集群配置
*/
private RedisClusterConfig clusterServer;
/**
* 客户端名称
*/
private String clientName = LockCommonConstant.LOCK_CLIENT_NAME;
/**
* 启动SSL终端识别
*/
private Boolean sslEnable = Boolean.TRUE;
/**
* SSL实现方式,确定采用哪种方式(JDK或OPENSSL)来实现SSL连接
*/
private String sslProvider = LockCommonConstant.JDK;
;
/**
* SSL正式路径
*/
private String sslCertPath;
/**
* SSL信任证书库密码
*/
private String sslCertPassword;
/**
* SSL钥匙库路径
*/
private String sslKeyPath;
/**
* SSL钥匙库密码
*/
private String sslKeyPassword;
/*getter and setter*/
public RedisSingleConfig getSingleServer() {
return singleServer;
}
public void setSingleServer(RedisSingleConfig singleServer) {
this.singleServer = singleServer;
}
public RedisClusterConfig getClusterServer() {
return clusterServer;
}
public void setClusterServer(RedisClusterConfig clusterServer) {
this.clusterServer = clusterServer;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public Boolean getSslEnable() {
return sslEnable;
}
public void setSslEnable(Boolean sslEnable) {
this.sslEnable = sslEnable;
}
public String getSslProvider() {
return sslProvider;
}
public void setSslProvider(String sslProvider) {
this.sslProvider = sslProvider;
}
public String getSslCertPath() {
return sslCertPath;
}
public void setSslCertPath(String sslCertPath) {
this.sslCertPath = sslCertPath;
}
public String getSslCertPassword() {
return sslCertPassword;
}
public void setSslCertPassword(String sslCertPassword) {
this.sslCertPassword = sslCertPassword;
}
public String getSslKeyPath() {
return sslKeyPath;
}
public void setSslKeyPath(String sslKeyPath) {
this.sslKeyPath = sslKeyPath;
}
public String getSslKeyPassword() {
return sslKeyPassword;
}
public void setSslKeyPassword(String sslKeyPassword) {
this.sslKeyPassword = sslKeyPassword;
}
}
package com.smart.hospital.common.lock.config;
import com.smart.hospital.common.lock.enums.ZkRetryPolicy;
import java.util.HashMap;
import java.util.Map;
public class ZkRetryPolicyStore {
private static Map<String, ZkRetryPolicy> retryPolicyMap = new HashMap<>();
static {
retryPolicyMap.put(ZkRetryPolicy.RETRY_EXPONENTIAL_BACKOFF.getPolicyName(), ZkRetryPolicy.RETRY_EXPONENTIAL_BACKOFF);
retryPolicyMap.put(ZkRetryPolicy.RETRY_FOREVER.getPolicyName(), ZkRetryPolicy.RETRY_FOREVER);
retryPolicyMap.put(ZkRetryPolicy.RETRY_NTIMES.getPolicyName(), ZkRetryPolicy.RETRY_NTIMES);
retryPolicyMap.put(ZkRetryPolicy.RETRY_UNTIL_ELAPSED.getPolicyName(), ZkRetryPolicy.RETRY_UNTIL_ELAPSED);
}
/**
* 根据字符串策略名,返回策略
*
* @param policyName
* @return
*/
public static ZkRetryPolicy getPolicy(String policyName) throws IllegalAccessException {
ZkRetryPolicy zkRetryPolicy = retryPolicyMap.get(policyName);
if (zkRetryPolicy == null) {
throw new IllegalAccessException("没有找到相应的策略,请检测参数是否正常,policyName的值为:" + policyName);
}
return zkRetryPolicy;
}
}
package com.smart.hospital.common.lock.config;
import com.smart.hospital.common.lock.config.zookeeper.ExponentialBackoffRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.ForeverRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.NTimesRetryConfig;
import com.smart.hospital.common.lock.config.zookeeper.UntilElapsedRetryConfig;
import com.smart.hospital.common.lock.enums.ZkRetryPolicy;
/**
* zookeeper配置类
*/
public class ZookeeperSchemeConfig {
private String address;
private int sessionTimeout;
private int connectionTimeoutMs;
private String retryPolicy = ZkRetryPolicy.RETRY_EXPONENTIAL_BACKOFF.getPolicyName();
/**
* 重试直到最大重试时长为止策略
*/
private UntilElapsedRetryConfig untilElapsedRetry;
/**
* 重试间隔休眠时间指数递增策略
*/
private ExponentialBackoffRetryConfig exponentialBackoffRetry = new ExponentialBackoffRetryConfig();
/**
* 一直重试,直到成功
*/
private ForeverRetryConfig foreverRetry;
/**
* 重试多次,提供一个构造函数,传入重试次数参数
*/
private NTimesRetryConfig ntimesRetry;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getSessionTimeout() {
return sessionTimeout;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public int getConnectionTimeoutMs() {
return connectionTimeoutMs;
}
public void setConnectionTimeoutMs(int connectionTimeoutMs) {
this.connectionTimeoutMs = connectionTimeoutMs;
}
public String getRetryPolicy() {
return retryPolicy;
}
public void setRetryPolicy(String retryPolicy) {
this.retryPolicy = retryPolicy;
}
public UntilElapsedRetryConfig getUntilElapsedRetry() {
return untilElapsedRetry;
}
public void setUntilElapsedRetry(UntilElapsedRetryConfig untilElapsedRetry) {
this.untilElapsedRetry = untilElapsedRetry;
}
public ExponentialBackoffRetryConfig getExponentialBackoffRetry() {
return exponentialBackoffRetry;
}
public void setExponentialBackoffRetry(ExponentialBackoffRetryConfig exponentialBackoffRetry) {
this.exponentialBackoffRetry = exponentialBackoffRetry;
}
public ForeverRetryConfig getForeverRetry() {
return foreverRetry;
}
public void setForeverRetry(ForeverRetryConfig foreverRetry) {
this.foreverRetry = foreverRetry;
}
public NTimesRetryConfig getNtimesRetry() {
return ntimesRetry;
}
public void setNtimesRetry(NTimesRetryConfig ntimesRetry) {
this.ntimesRetry = ntimesRetry;
}
}
package com.smart.hospital.common.lock.config.redis;
import com.smart.hospital.common.lock.constant.LoadBalancerTypeConstant;
import com.smart.hospital.common.lock.constant.SubReadModeTypeConstant;
/**
* 集群模式配置
*/
public class RedisClusterConfig {
/**
* 集群节点地址
*/
private String nodeAddresses;
/**
* 集群扫描间隔时间
*/
private int scanInterval = 1000;
/**
* 读取操作的负载均衡模式
*/
private String readMode = SubReadModeTypeConstant.SLAVE;
/**
* 订阅操作的负载均衡模式
*/
private String subMode = SubReadModeTypeConstant.SLAVE;
/**
* 负载均衡算法类的选择,默认:轮询调度算法
*/
private String loadBalancer = LoadBalancerTypeConstant.ROUND_ROBIN_LOAD_BALANCER;
/**
* 默认权重值,当负载均衡算法是权重轮询调度算法时该属性有效
*/
private int defaultWeight = 0;
/**
* 权重值设置,格式为 host1:port1,权重值1;host2:port2,权重值2 当负载均衡算法是权重轮询调度算法时该属性有效
*/
private String weightMaps;
/**
* 从节点发布和订阅连接的最小空闲连接数
*/
private int subConnMinIdleSize = 1;
/**
* 从节点发布和订阅连接池大小
*/
private int subConnPoolSize = 50;
/**
* 从节点最小空闲连接数
*/
private int slaveConnMinIdleSize = 32;
/**
* 从节点连接池大小
*/
private int slaveConnPoolSize = 64;
/**
* 主节点最小空闲连接数
*/
private int masterConnMinIdleSize = 32;
/**
* 主节点连接池大小
*/
private int masterConnPoolSize = 64;
/**
* 连接空闲超时,单位:毫秒
*/
private int idleConnTimeout = 10000;
/**
* 连接超时,单位:毫秒
*/
private int connTimeout = 10000;
/**
* 命令等待超时,单位:毫秒
*/
private int timeout = 3000;
/**
* 命令失败重试次数
*/
private int retryAttempts = 3;
/**
* 命令重试发送时间间隔,单位:毫秒
*/
private int retryInterval = 1500;
/**
* 密码
*/
private String password;
/**
* 单个连接最大订阅数量
*/
private int subPerConn = 5;
public String getNodeAddresses() {
return nodeAddresses;
}
public void setNodeAddresses(String nodeAddresses) {
this.nodeAddresses = nodeAddresses;
}
public int getScanInterval() {
return scanInterval;
}
public void setScanInterval(int scanInterval) {
this.scanInterval = scanInterval;
}
public String getReadMode() {
return readMode;
}
public void setReadMode(String readMode) {
this.readMode = readMode;
}
public String getSubMode() {
return subMode;
}
public void setSubMode(String subMode) {
this.subMode = subMode;
}
public String getLoadBalancer() {
return loadBalancer;
}
public void setLoadBalancer(String loadBalancer) {
this.loadBalancer = loadBalancer;
}
public int getDefaultWeight() {
return defaultWeight;
}
public void setDefaultWeight(int defaultWeight) {
this.defaultWeight = defaultWeight;
}
public String getWeightMaps() {
return weightMaps;
}
public void setWeightMaps(String weightMaps) {
this.weightMaps = weightMaps;
}
public int getSubConnMinIdleSize() {
return subConnMinIdleSize;
}
public void setSubConnMinIdleSize(int subConnMinIdleSize) {
this.subConnMinIdleSize = subConnMinIdleSize;
}
public int getSubConnPoolSize() {
return subConnPoolSize;
}
public void setSubConnPoolSize(int subConnPoolSize) {
this.subConnPoolSize = subConnPoolSize;
}
public int getSlaveConnMinIdleSize() {
return slaveConnMinIdleSize;
}
public void setSlaveConnMinIdleSize(int slaveConnMinIdleSize) {
this.slaveConnMinIdleSize = slaveConnMinIdleSize;
}
public int getSlaveConnPoolSize() {
return slaveConnPoolSize;
}
public void setSlaveConnPoolSize(int slaveConnPoolSize) {
this.slaveConnPoolSize = slaveConnPoolSize;
}
public int getMasterConnMinIdleSize() {
return masterConnMinIdleSize;
}
public void setMasterConnMinIdleSize(int masterConnMinIdleSize) {
this.masterConnMinIdleSize = masterConnMinIdleSize;
}
public int getMasterConnPoolSize() {
return masterConnPoolSize;
}
public void setMasterConnPoolSize(int masterConnPoolSize) {
this.masterConnPoolSize = masterConnPoolSize;
}
public int getIdleConnTimeout() {
return idleConnTimeout;
}
public void setIdleConnTimeout(int idleConnTimeout) {
this.idleConnTimeout = idleConnTimeout;
}
public int getConnTimeout() {
return connTimeout;
}
public void setConnTimeout(int connTimeout) {
this.connTimeout = connTimeout;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getRetryAttempts() {
return retryAttempts;
}
public void setRetryAttempts(int retryAttempts) {
this.retryAttempts = retryAttempts;
}
public int getRetryInterval() {
return retryInterval;
}
public void setRetryInterval(int retryInterval) {
this.retryInterval = retryInterval;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getSubPerConn() {
return subPerConn;
}
public void setSubPerConn(int subPerConn) {
this.subPerConn = subPerConn;
}
}
package com.smart.hospital.common.lock.config.redis;
/**
* redis单机模式配置
*/
public class RedisSingleConfig {
/**
* 节点连接地址
*/
private String address = "localhost";
/**
* 节点端口号
*/
private int port = 6379;
/**
* 数据库编号
*/
private int database = 0;
/**
* 连接密码
*/
private String password;
/**
* 单个连接最大的订阅数量
*/
private int subPerConn = 5;
/**
* 发布和订阅连接的最小空闲连接数
*/
private int subConnMinIdleSize = 1;
/**
* 发布和订阅连接池大小
*/
private int subConnPoolSize = 50;
/**
* 最小空闲连接数
*/
private int connMinIdleSize = 32;
/**
* 连接池大小
*/
private int connPoolSize = 64;
/**
* 是否启用DNS监测
*/
private boolean dnsMonitoring = false;
/**
* DNS监测时间间隔,单位:毫秒,该配置需要dnsMonitoring设为true
*/
private int dnsMonitoringInterval = 5000;
/**
* 连接空闲超时,单位:毫秒
*/
private int idleConnTimeout = 10000;
/**
* 连接是否可用
*/
private boolean keepAlive = false;
/**
* 连接超时,单位:毫秒
*/
private int connTimeout = 10000;
/**
* 命令等待超时,单位:毫秒
*/
private int timeout = 3000;
/**
* 命令失败重试次数 如果尝试达到 retryAttempts(命令失败重试次数)
* 仍然不能将命令发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
*/
private int retryAttempts = 3;
/**
* 命令重试发送时间间隔,单位:毫秒
*/
private int retryInterval = 1500;
/*getter and setter*/
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getDatabase() {
return database;
}
public void setDatabase(int database) {
this.database = database;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getSubPerConn() {
return subPerConn;
}
public void setSubPerConn(int subPerConn) {
this.subPerConn = subPerConn;
}
public int getSubConnMinIdleSize() {
return subConnMinIdleSize;
}
public void setSubConnMinIdleSize(int subConnMinIdleSize) {
this.subConnMinIdleSize = subConnMinIdleSize;
}
public int getSubConnPoolSize() {
return subConnPoolSize;
}
public void setSubConnPoolSize(int subConnPoolSize) {
this.subConnPoolSize = subConnPoolSize;
}
public int getConnMinIdleSize() {
return connMinIdleSize;
}
public void setConnMinIdleSize(int connMinIdleSize) {
this.connMinIdleSize = connMinIdleSize;
}
public int getConnPoolSize() {
return connPoolSize;
}
public void setConnPoolSize(int connPoolSize) {
this.connPoolSize = connPoolSize;
}
public boolean isDnsMonitoring() {
return dnsMonitoring;
}
public void setDnsMonitoring(boolean dnsMonitoring) {
this.dnsMonitoring = dnsMonitoring;
}
public int getDnsMonitoringInterval() {
return dnsMonitoringInterval;
}
public void setDnsMonitoringInterval(int dnsMonitoringInterval) {
this.dnsMonitoringInterval = dnsMonitoringInterval;
}
public int getIdleConnTimeout() {
return idleConnTimeout;
}
public void setIdleConnTimeout(int idleConnTimeout) {
this.idleConnTimeout = idleConnTimeout;
}
public boolean isKeepAlive() {
return keepAlive;
}
public void setKeepAlive(boolean keepAlive) {
this.keepAlive = keepAlive;
}
public int getConnTimeout() {
return connTimeout;
}
public void setConnTimeout(int connTimeout) {
this.connTimeout = connTimeout;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getRetryAttempts() {
return retryAttempts;
}
public void setRetryAttempts(int retryAttempts) {
this.retryAttempts = retryAttempts;
}
public int getRetryInterval() {
return retryInterval;
}
public void setRetryInterval(int retryInterval) {
this.retryInterval = retryInterval;
}
}
package com.smart.hospital.common.lock.config.zookeeper;
public class ExponentialBackoffRetryConfig {
private int baseSleepTimeMs=1000;
private int maxRetries=3;
private int maxSleepMs = Integer.MAX_VALUE;
public int getBaseSleepTimeMs() {
return baseSleepTimeMs;
}
public void setBaseSleepTimeMs(int baseSleepTimeMs) {
this.baseSleepTimeMs = baseSleepTimeMs;
}
public int getMaxRetries() {
return maxRetries;
}
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getMaxSleepMs() {
return maxSleepMs;
}
public void setMaxSleepMs(int maxSleepMs) {
this.maxSleepMs = maxSleepMs;
}
}
package com.smart.hospital.common.lock.config.zookeeper;
public class ForeverRetryConfig {
private int retryIntervalMs;
public int getRetryIntervalMs() {
return retryIntervalMs;
}
public void setRetryIntervalMs(int retryIntervalMs) {
this.retryIntervalMs = retryIntervalMs;
}
}
package com.smart.hospital.common.lock.config.zookeeper;
public class NTimesRetryConfig {
private int n;
private int sleepMsBetweenRetries;
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
public int getSleepMsBetweenRetries() {
return sleepMsBetweenRetries;
}
public void setSleepMsBetweenRetries(int sleepMsBetweenRetries) {
this.sleepMsBetweenRetries = sleepMsBetweenRetries;
}
}
package com.smart.hospital.common.lock.config.zookeeper;
public class UntilElapsedRetryConfig {
private int maxElapsedTimeMs;
private int sleepMsBetweenRetries;
public int getMaxElapsedTimeMs() {
return maxElapsedTimeMs;
}
public void setMaxElapsedTimeMs(int maxElapsedTimeMs) {
this.maxElapsedTimeMs = maxElapsedTimeMs;
}
public int getSleepMsBetweenRetries() {
return sleepMsBetweenRetries;
}
public void setSleepMsBetweenRetries(int sleepMsBetweenRetries) {
this.sleepMsBetweenRetries = sleepMsBetweenRetries;
}
}
package com.smart.hospital.common.lock.constant;
/**
* 负载均衡算法类型
*/
public interface LoadBalancerTypeConstant {
/**
* 随机
*/
String RANDOM_LOAD_BALANCER = "RandomLoadBalancer";
/**
* 轮询
*/
String ROUND_ROBIN_LOAD_BALANCER = "RoundRobinLoadBalancer";
/**
* 权重
*/
String WEIGHTED_ROUND_ROBIN_BALANCER = "WeightedRoundRobinBalancer";
}
package com.smart.hospital.common.lock.constant;
/**
* 公共常量
*/
public interface LockCommonConstant {
/**
* 默认客户端名字
*/
String LOCK_CLIENT_NAME = "Ladlee:Lock";
/**
* 默认SSL实现方式:JDK
*/
String JDK = "JDK";
/**
* 逗号
*/
String COMMA = ",";
/**
* 冒号
*/
String COLON = ":";
/**
* 斜线
*/
String OBLIQUE = "/";
/**
* 分号
*/
String SEMICOLON = ";";
/**
* redis默认URL前缀
*/
String REDIS_URL_PREFIX = "redis://";
/**
* 锁的key的分隔符
*/
String KEY_SPLIT_MARK = ":";
/**
* 锁的前缀
*/
String KEY_PREFIX = "ladlee" + KEY_SPLIT_MARK + "lock" + KEY_SPLIT_MARK + "key" + KEY_SPLIT_MARK;
String LOCK_CLIENT_BEAN_NAME = "lockClient";
}
package com.smart.hospital.common.lock.constant;
/**
* 读取操作/订阅操作的负载均衡模式常量
*/
public interface SubReadModeTypeConstant {
String SLAVE = "SLAVE";
String MASTER = "MASTER";
String MASTER_SLAVE = "MASTER_SLAVE";
}
package com.smart.hospital.common.lock.custom;
import com.smart.hospital.common.lock.advisor.intercept.LockInterceptor;
@FunctionalInterface
public interface InterceptorCustomizer {
/**
* 可以对拦截器中的 RedissonClient 和 redissonClientBeanName进行更改
*
* @param interceptor
*/
void customize(LockInterceptor interceptor);
}
package com.smart.hospital.common.lock.custom;
import com.smart.hospital.common.lock.properties.LockProperties;
/**
* 分布式锁配置类自定义
*/
@FunctionalInterface
public interface PropertiesCustomizer {
/**
* 给机会对LockProperties文件进行修改
*
* @param properties
*/
void customize(LockProperties properties);
}
package com.smart.hospital.common.lock.custom.impl;
import com.smart.hospital.common.lock.custom.PropertiesCustomizer;
import com.smart.hospital.common.lock.properties.LockProperties;
import org.redisson.codec.MarshallingCodec;
public class CodecPropertiesCustomizer implements PropertiesCustomizer {
@Override
public void customize(LockProperties properties) {
// 3.16.1默认使用的就是这个序列化类,这里只是演示使用自定义改变的方式
properties.setCodec(new MarshallingCodec());
}
}
//package com.smart.hospital.common.lock.enums;
//
///**
// * zookeeper锁类型
// */
//public enum InterProcess {
//
// /**
// * 分布式可重入排它锁
// */
// MUTEX,
// /**
// * 分布式排它锁
// */
// SEMAPHORE_MUTEX,
// /**
// * 分布式读锁
// */
// READ,
// /**
// * 分布式写锁
// */
// WRITE,
// /**
// * 将多个锁作为单个实体管理的容器
// */
// MULTI
//
//}
package com.smart.hospital.common.lock.enums;
/**
* 锁的实现方式
*/
public enum LockScheme {
REDIS(LockSchemeConstant.REDIS),
ZOOKEEPER(LockSchemeConstant.ZOOKEEPER);
private String scheme;
LockScheme(String scheme) {
this.scheme = scheme;
}
public String getScheme() {
return scheme;
}
public static LockScheme find(String scheme) {
if (scheme == null) {
return null;
}
for (LockScheme value : LockScheme.values()) {
if (value.getScheme().equals(scheme)) {
return value;
}
}
return null;
}
public interface LockSchemeConstant {
String REDIS = "redis";
String ZOOKEEPER = "zookeeper";
}
}
package com.smart.hospital.common.lock.enums;
/**
* 锁类型
*/
public enum LockType {
/**
* 可重入锁
*/
REENTRANT,
/**
* 公平锁
*/
FAIR,
/**
* 联锁
*/
MULTI,
/**
* 红锁
*/
RED,
/**
* 读锁
*/
READ,
/**
* 写锁
*/
WRITE,
/**
* 分布式可重入排它锁(zookeeper)
*/
MUTEX,
/**
* 分布式排它锁(zookeeper)
*/
SEMAPHORE_MUTEX;
}
package com.smart.hospital.common.lock.enums;
/**
* redis的运行模式
*/
public enum ServerPattern {
/**
* 单机模式(单节点)
*/
SINGLE("single"),
/**
* 集群模式,除了适用于Redis集群环境,也适用于任何云计算服务商提供的集群模式
*/
CLUSTER("cluster"),
/**
* 云托管模式,适用于任何由云计算运营商提供的Redis云服务,包括亚马逊云的AWS ElastiCache、微软云的Azure Redis 缓存和阿里云(Aliyun)的云数据库Redis版
*/
REPLICATED("replicated"),
/**
* 哨兵模式
*/
SENTINEL("sentinel"),
/**
* 主从模式
*/
MASTER_SLAVE("master_slave");
private String pattern;
ServerPattern(String pattern) {
this.pattern = pattern;
}
public String getPattern() {
return pattern;
}
}
package com.smart.hospital.common.lock.enums;
public enum ZkRetryPolicy {
RETRY_FOREVER("forever"),
RETRY_NTIMES("ntimes"),
RETRY_EXPONENTIAL_BACKOFF("exponential_backoff"),
RETRY_UNTIL_ELAPSED("until_elapsed");
private String policyName;
private ZkRetryPolicy(String policyName) {
this.policyName = policyName;
}
public String getPolicyName() {
return this.policyName;
}
}
package com.smart.hospital.common.lock.key;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 分布式锁的key信息
*/
public interface LockKey<T, M> {
/**
* 获取key
*
* @return
*/
M getKey();
/**
* 设置Key
*
* @param key
*/
void setKey(T key);
/**
* 获取scheme
*
* @return
*/
LockScheme getLockScheme();
/**
* 获取lockType
*
* @return
*/
LockType getLockType();
long getLeaseTime();
long getWaitTime();
TimeUnit getTimeUnit();
default List<String> getLockPath() {
return null;
}
}
package com.smart.hospital.common.lock.key;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class RedisLockKey implements LockKey<String, List<String>> {
private long leaseTime = -1;
private long waitTime = -1;
private TimeUnit timeUnit = TimeUnit.SECONDS;
private LockScheme lockScheme;
private LockType lockType;
/**
* key列表
*/
private List<String> keyList;
public RedisLockKey(LockType lockType, LockScheme lockScheme, long leaseTime, long waitTime, TimeUnit timeUnit, List<String> keyList) {
this.lockType = lockType;
this.lockScheme = lockScheme;
this.leaseTime = leaseTime;
this.waitTime = waitTime;
this.timeUnit = timeUnit;
this.keyList = keyList;
}
@Override
public long getLeaseTime() {
return leaseTime;
}
@Override
public long getWaitTime() {
return waitTime;
}
@Override
public TimeUnit getTimeUnit() {
return timeUnit;
}
@Override
public List<String> getKey() {
return this.keyList;
}
@Override
public void setKey(String key) {
this.keyList.add(key);
}
@Override
public LockScheme getLockScheme() {
return this.lockScheme;
}
@Override
public LockType getLockType() {
return this.lockType;
}
@Override
public String toString() {
return "RedisLockKey{" +
"leaseTime=" + leaseTime +
", waitTime=" + waitTime +
", timeUnit=" + timeUnit +
", lockScheme=" + lockScheme +
", lockType=" + lockType +
", keyList=" + keyList +
'}';
}
}
package com.smart.hospital.common.lock.key;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ZookeeperLockKey implements LockKey<String, List<String>> {
private LockType lockType;
private long waitTime = -1;
private TimeUnit timeUnit = TimeUnit.SECONDS;
/**
* key列表
*/
private List<String> keyList;
public ZookeeperLockKey(LockType lockType, long waitTime, TimeUnit timeUnit, List<String> keyList) {
this.lockType = lockType;
this.waitTime = waitTime;
this.timeUnit = timeUnit;
this.keyList = keyList;
}
@Override
public List<String> getLockPath() {
List<String> pathList = new ArrayList<String>();
for (String key : this.getKey()) {
pathList.add(LockCommonConstant.OBLIQUE + key.replace(LockCommonConstant.KEY_SPLIT_MARK, LockCommonConstant.OBLIQUE));
}
return pathList;
}
@Override
public List<String> getKey() {
return this.keyList;
}
@Override
public void setKey(String key) {
if (this.keyList != null) {
this.keyList.add(key);
}
throw new IllegalStateException("Key的存储列表没有被初始化");
}
@Override
public LockScheme getLockScheme() {
return null;
}
@Override
public LockType getLockType() {
return this.lockType;
}
@Override
public long getLeaseTime() {
return -1;
}
@Override
public long getWaitTime() {
return this.waitTime;
}
@Override
public TimeUnit getTimeUnit() {
return this.timeUnit;
}
}
package com.smart.hospital.common.lock.key.strategy;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.RedisLockKey;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractKeyStrategy implements KeyStrategy {
/**
* 锁类型
*/
protected LockScheme scheme;
/**
* 类名称
*/
protected String className;
/**
* 方法名称
*/
protected String methodName;
/**
* 方法
*/
protected Method realMethod;
/**
* 方法参数
*/
protected Object[] args;
/**
* @Lock的属性值
*/
protected LockAttribute attribute;
public AbstractKeyStrategy(String className, String methodName, Method realMethod, Object[] args, LockScheme scheme, LockAttribute attribute) {
this.className = className;
this.methodName = methodName;
this.realMethod = realMethod;
this.args = args;
this.scheme = scheme;
this.attribute = attribute;
}
/**
* 获取类名称
*
* @return
*/
public String getSimpleClassName() {
String[] split = this.className.split("\\.");
return split[split.length - 1];
}
/**
* 包装锁的key(在redis里的key)
*
* @param valTag
* @return
*/
protected String wrapKey(String valTag) {
return getSimpleClassName() + LockCommonConstant.KEY_SPLIT_MARK + this.methodName + LockCommonConstant.KEY_SPLIT_MARK + valTag;
}
protected LockKey<String, List<String>> buildLockKey() {
LockKey<String, List<String>> lockKey;
if (this.scheme == LockScheme.REDIS) {
lockKey = new RedisLockKey(this.attribute.getLockType(), this.scheme, attribute.getLeaseTime(), attribute.getWaitTime(), attribute.getTimeUnit(), new ArrayList<>());
} else {
throw new IllegalArgumentException("目前只支持Redis");
}
return lockKey;
}
@Override
public LockKey<String, List<String>> buildKey() {
LockKey<String, List<String>> key = buildLockKey();
buildKeyItem(key);
return key;
}
protected abstract void buildKeyItem(LockKey<String, List<String>> lockKey);
public LockScheme getScheme() {
return scheme;
}
public void setScheme(LockScheme scheme) {
this.scheme = scheme;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Method getRealMethod() {
return realMethod;
}
public void setRealMethod(Method realMethod) {
this.realMethod = realMethod;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public LockAttribute getAttribute() {
return attribute;
}
public void setAttribute(LockAttribute attribute) {
this.attribute = attribute;
}
}
package com.smart.hospital.common.lock.key.strategy;
import com.smart.hospital.common.lock.annotation.Key;
import com.smart.hospital.common.lock.key.LockKey;
import java.lang.annotation.Annotation;
import java.util.List;
/**
* 获取key类型的策略
*/
public interface KeyStrategy {
Class<? extends Annotation> KEY_ANNOTATION_CLASS = Key.class;
/**
* 构建key
* @return
*/
LockKey<String, List<String>> buildKey();
}
package com.smart.hospital.common.lock.key.strategy.impl;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.strategy.AbstractKeyStrategy;
import java.lang.reflect.Method;
import java.util.List;
public class ClassKeyStrategy extends AbstractKeyStrategy {
public ClassKeyStrategy(String className, String methodName, Method realMethod, Object[] args, LockScheme scheme, LockAttribute attribute) {
super(className, methodName, realMethod, args, scheme, attribute);
}
@Override
protected void buildKeyItem(LockKey<String, List<String>> lockKey) {
}
}
package com.smart.hospital.common.lock.key.strategy.impl;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.strategy.AbstractKeyStrategy;
import java.lang.reflect.Method;
import java.util.List;
public class FieldKeyStrategy extends AbstractKeyStrategy {
public FieldKeyStrategy(String className, String methodName, Method realMethod, Object[] args, LockScheme scheme, LockAttribute attribute) {
super(className, methodName, realMethod, args, scheme, attribute);
}
@Override
protected void buildKeyItem(LockKey<String, List<String>> lockKey) {
}
}
package com.smart.hospital.common.lock.key.strategy.impl;
import cn.hutool.core.util.ArrayUtil;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.annotation.Key;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.strategy.AbstractKeyStrategy;
import com.smart.hospital.common.lock.key.strategy.KeyStrategy;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
@Slf4j
public class MethodKeyStrategy extends AbstractKeyStrategy {
public MethodKeyStrategy(String className, String methodName, Method realMethod, Object[] args, LockScheme scheme, LockAttribute attribute) {
super(className, methodName, realMethod, args, scheme, attribute);
}
@Override
protected void buildKeyItem(LockKey<String, List<String>> lockKey) {
String[] values = ((Key) realMethod.getAnnotation(KeyStrategy.KEY_ANNOTATION_CLASS)).value();
if (ArrayUtil.isEmpty(args)) {
for (String key : values) {
lockKey.setKey(key);
}
} else {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
Class<?> argClass = arg.getClass();
Field[] fields = argClass.getDeclaredFields();
for (String key : values) {
String[] propertyName = key.split("\\.");
String[] classNames = argClass.getName().split("\\.");
if (propertyName[0].equals(classNames[classNames.length - 1])) {
for (Field field : fields) {
field.setAccessible(true);
if (field.getName().equals(propertyName[1])) {
try {
lockKey.setKey(wrapKey(field.get(arg).toString()));
} catch (Exception ex) {
throw new IllegalArgumentException("构建Key失败", ex);
}
}
}
}
}
}
}
}
}
package com.smart.hospital.common.lock.key.strategy.impl;
import com.smart.hospital.common.lock.advisor.attribute.LockAttribute;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.key.strategy.AbstractKeyStrategy;
import com.smart.hospital.common.lock.key.strategy.KeyStrategy;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
public class ParameterKeyStrategy extends AbstractKeyStrategy {
public ParameterKeyStrategy(String className, String methodName, Method realMethod, Object[] args, LockScheme scheme, LockAttribute attribute) {
super(className, methodName, realMethod, args, scheme, attribute);
}
@Override
protected void buildKeyItem(LockKey<String, List<String>> lockKey) {
Parameter[] parameters = realMethod.getParameters();
if(parameters != null && parameters.length > 0){
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].isAnnotationPresent(KeyStrategy.KEY_ANNOTATION_CLASS)) {
lockKey.setKey(wrapKey(args[i].toString()));
}
}
}
}
}
package com.smart.hospital.common.lock.properties;
import com.smart.hospital.common.lock.config.RedisSchemeConfig;
import com.smart.hospital.common.lock.config.ZookeeperSchemeConfig;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.ServerPattern;
import org.redisson.client.codec.Codec;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static com.smart.hospital.common.lock.properties.LockProperties.LOCK_PREFIX;
/**
* 分布式锁配置类
*/
@ConfigurationProperties(prefix = LOCK_PREFIX)
public class LockProperties {
public static final String LOCK_PREFIX = "spring.lock";
public static final String PROPERTY_NAME = "lock-scheme";
/**
* 序列化方式
*/
private Codec codec;
/**
* 锁的实现方式,默认redis
*/
private String lockScheme = LockScheme.REDIS.getScheme();
/**
* 默认是redis的单机模式
*/
private String pattern = ServerPattern.SINGLE.getPattern();
/**
* redis配置
*/
private RedisSchemeConfig redis;
/**
* zookeeper配置
*/
private ZookeeperSchemeConfig zookeeper;
public String getLockScheme() {
return lockScheme;
}
public void setLockScheme(String lockScheme) {
this.lockScheme = lockScheme;
}
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
public RedisSchemeConfig getRedis() {
return redis;
}
public void setRedis(RedisSchemeConfig redis) {
this.redis = redis;
}
public Codec getCodec() {
return codec;
}
public void setCodec(Codec codec) {
this.codec = codec;
}
public ZookeeperSchemeConfig getZookeeper() {
return zookeeper;
}
public void setZookeeper(ZookeeperSchemeConfig zookeeper) {
this.zookeeper = zookeeper;
}
}
package com.smart.hospital.common.lock.provider.manager;
import com.smart.hospital.common.lock.config.InitConfig;
import org.redisson.api.RedissonClient;
public interface PatternManager {
/**
* 初始化配置
*/
RedissonClient initConfig(InitConfig baseConfig);
}
package com.smart.hospital.common.lock.provider.manager;
import com.smart.hospital.common.lock.config.InitConfig;
import com.smart.hospital.common.lock.provider.pattern.PatternProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import java.util.Collections;
import java.util.List;
/**
* 管理redis的模式,并进行配置
*/
public class RedisServerPatternManager implements PatternManager, InitializingBean {
private static final Log logger = LogFactory.getLog(RedisServerPatternManager.class);
private List<PatternProvider> providers = Collections.emptyList();
public RedisServerPatternManager(List<PatternProvider> providers) {
this.providers = providers;
}
@Override
public RedissonClient initConfig(InitConfig baseConfig) {
for (PatternProvider provider : getProviders()) {
if (!provider.supports(baseConfig.getPattern())) {
continue;
}
logger.debug("PatternProvider attempt using " + provider.getClass().getName());
return provider.init(baseConfig);
}
throw new IllegalArgumentException("没用合适的创建 RedissonClient 的provider");
}
@Override
public void afterPropertiesSet() throws Exception {
checkState();
}
private void checkState() {
if (providers == null || providers.isEmpty()) {
throw new IllegalArgumentException("A list of PatternProviders is required");
}
}
public List<PatternProvider> getProviders() {
return providers;
}
}
package com.smart.hospital.common.lock.provider.pattern;
import com.smart.hospital.common.lock.config.InitConfig;
import org.redisson.api.RedissonClient;
/**
* 配置接口
*/
public interface PatternProvider {
/**
* 初始化配置
*
* @param baseConfig
*/
RedissonClient init(InitConfig baseConfig);
/**
* 是否是支持的类型
*
* @return
*/
boolean supports(String pattern);
}
package com.smart.hospital.common.lock.provider.pattern;
import cn.hutool.core.util.StrUtil;
import com.smart.hospital.common.lock.config.InitConfig;
import com.smart.hospital.common.lock.config.RedisSchemeConfig;
import com.smart.hospital.common.lock.config.redis.RedisClusterConfig;
import com.smart.hospital.common.lock.constant.LoadBalancerTypeConstant;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.constant.SubReadModeTypeConstant;
import com.smart.hospital.common.lock.enums.ServerPattern;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.ReadMode;
import org.redisson.config.SubscriptionMode;
import org.redisson.connection.balancer.LoadBalancer;
import org.redisson.connection.balancer.RandomLoadBalancer;
import org.redisson.connection.balancer.RoundRobinLoadBalancer;
import org.redisson.connection.balancer.WeightedRoundRobinBalancer;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class RedisClusterProvider implements PatternProvider {
@Override
public RedissonClient init(InitConfig baseConfig) {
ClusterServersConfig clusterServerConfig = baseConfig.useClusterServers();
RedisSchemeConfig redisSchemeConfig = baseConfig.getLockProperties().getRedis();
RedisClusterConfig clusterConfig = redisSchemeConfig.getClusterServer();
String[] addressArr = clusterConfig.getNodeAddresses().split(LockCommonConstant.COMMA);
Arrays.asList(addressArr).forEach(address -> clusterServerConfig
.addNodeAddress(String.format("%s%s", LockCommonConstant.REDIS_URL_PREFIX, address)));
clusterServerConfig.setScanInterval(clusterConfig.getScanInterval());
ReadMode readMode = getReadMode(clusterConfig.getReadMode());
Assert.notNull(readMode, "未知读取操作的负载均衡模式类型");
clusterServerConfig.setReadMode(readMode);
SubscriptionMode subscriptionMode = getSubscriptionMode(clusterConfig.getSubMode());
Assert.notNull(readMode, "未知订阅操作的负载均衡模式类型");
clusterServerConfig.setSubscriptionMode(subscriptionMode);
LoadBalancer loadBalancer = getLoadBalancer(clusterConfig.getLoadBalancer(), clusterConfig.getWeightMaps(),
clusterConfig.getDefaultWeight());
Assert.notNull(readMode, "未知负载均衡算法类型");
clusterServerConfig.setLoadBalancer(loadBalancer);
clusterServerConfig.setSubscriptionConnectionMinimumIdleSize(clusterConfig.getSubConnMinIdleSize());
clusterServerConfig.setSubscriptionConnectionPoolSize(clusterConfig.getSubConnPoolSize());
clusterServerConfig.setSlaveConnectionMinimumIdleSize(clusterConfig.getSlaveConnMinIdleSize());
clusterServerConfig.setSlaveConnectionPoolSize(clusterConfig.getSlaveConnPoolSize());
clusterServerConfig.setMasterConnectionMinimumIdleSize(clusterConfig.getMasterConnMinIdleSize());
clusterServerConfig.setMasterConnectionPoolSize(clusterConfig.getMasterConnPoolSize());
clusterServerConfig.setIdleConnectionTimeout(clusterConfig.getIdleConnTimeout());
clusterServerConfig.setConnectTimeout(clusterConfig.getConnTimeout());
clusterServerConfig.setTimeout(clusterConfig.getTimeout());
clusterServerConfig.setRetryAttempts(clusterConfig.getRetryAttempts());
clusterServerConfig.setRetryInterval(clusterConfig.getRetryInterval());
clusterServerConfig.setPassword(clusterConfig.getPassword());
clusterServerConfig.setSubscriptionsPerConnection(clusterConfig.getSubPerConn());
clusterServerConfig.setClientName(redisSchemeConfig.getClientName());
return Redisson.create(baseConfig);
}
@Override
public boolean supports(String pattern) {
if (StrUtil.isBlank(pattern)) {
return false;
}
return ServerPattern.CLUSTER.getPattern().equals(pattern);
}
/**
* 根据readModeType返回ReadMode
*
* @param readModeType 读取操作的负载均衡模式类型
* @return ReadMode OR NULL
*/
private ReadMode getReadMode(String readModeType) {
if (SubReadModeTypeConstant.SLAVE.equals(readModeType)) {
return ReadMode.SLAVE;
}
if (SubReadModeTypeConstant.MASTER.equals(readModeType)) {
return ReadMode.MASTER;
}
if (SubReadModeTypeConstant.MASTER_SLAVE.equals(readModeType)) {
return ReadMode.MASTER_SLAVE;
}
return null;
}
/**
* 根据subscriptionModeType返回SubscriptionMode
*
* @param subscriptionModeType 订阅操作的负载均衡模式类型
* @return SubscriptionMode OR NULL
*/
private SubscriptionMode getSubscriptionMode(String subscriptionModeType) {
if (SubReadModeTypeConstant.SLAVE.equals(subscriptionModeType)) {
return SubscriptionMode.SLAVE;
}
if (SubReadModeTypeConstant.MASTER.equals(subscriptionModeType)) {
return SubscriptionMode.MASTER;
}
return null;
}
/**
* 根据用户的配置类型设置对应的LoadBalancer
*
* @param loadBalancerType 负载均衡算法类名
* @param customerWeightMaps 权重值设置,当负载均衡算法是权重轮询调度算法时该属性有效
* @param defaultWeight 默认权重值,当负载均衡算法是权重轮询调度算法时该属性有效
* @return LoadBalancer OR NULL
*/
private LoadBalancer getLoadBalancer(String loadBalancerType, String customerWeightMaps, int defaultWeight) {
if (LoadBalancerTypeConstant.RANDOM_LOAD_BALANCER.equals(loadBalancerType)) {
return new RandomLoadBalancer();
}
if (LoadBalancerTypeConstant.ROUND_ROBIN_LOAD_BALANCER.equals(loadBalancerType)) {
return new RoundRobinLoadBalancer();
}
if (LoadBalancerTypeConstant.WEIGHTED_ROUND_ROBIN_BALANCER.equals(loadBalancerType)) {
Map<String, Integer> weights = new HashMap<>(16);
String[] weightMaps = customerWeightMaps.split(LockCommonConstant.SEMICOLON);
Arrays.asList(weightMaps)
.forEach(weightMap -> weights.put(
LockCommonConstant.REDIS_URL_PREFIX + weightMap.split(LockCommonConstant.COMMA)[0],
Integer.parseInt(weightMap.split(LockCommonConstant.COMMA)[1])));
return new WeightedRoundRobinBalancer(weights, defaultWeight);
}
return null;
}
}
package com.smart.hospital.common.lock.provider.pattern;
import cn.hutool.core.util.StrUtil;
import com.smart.hospital.common.lock.config.InitConfig;
import com.smart.hospital.common.lock.config.RedisSchemeConfig;
import com.smart.hospital.common.lock.config.redis.RedisSingleConfig;
import com.smart.hospital.common.lock.constant.LockCommonConstant;
import com.smart.hospital.common.lock.enums.ServerPattern;
import lombok.SneakyThrows;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.SingleServerConfig;
import org.redisson.config.SslProvider;
import java.net.URL;
public class RedisSingleProvider implements PatternProvider {
@Override
@SneakyThrows
public RedissonClient init(InitConfig baseConfig) {
SingleServerConfig singleServerConfig = baseConfig.useSingleServer();
RedisSchemeConfig redisSchemeConfig = baseConfig.getLockProperties().getRedis();
RedisSingleConfig singleConfig = redisSchemeConfig.getSingleServer();
// 连接地址
singleServerConfig.setAddress(String.format("%s%s%s%s", LockCommonConstant.REDIS_URL_PREFIX, singleConfig.getAddress(), LockCommonConstant.COLON, singleConfig.getPort()));
// 客户端名称
singleServerConfig.setClientName(redisSchemeConfig.getClientName());
singleServerConfig.setConnectionMinimumIdleSize(singleConfig.getConnMinIdleSize());
singleServerConfig.setConnectionPoolSize(singleConfig.getConnPoolSize());
singleServerConfig.setConnectTimeout(singleConfig.getConnTimeout());
singleServerConfig.setDatabase(singleConfig.getDatabase());
singleServerConfig.setDnsMonitoringInterval(singleConfig.getDnsMonitoringInterval());
singleServerConfig.setIdleConnectionTimeout(singleConfig.getIdleConnTimeout());
singleServerConfig.setKeepAlive(singleConfig.isKeepAlive());
singleServerConfig.setPassword(singleConfig.getPassword());
singleServerConfig.setRetryAttempts(singleConfig.getRetryAttempts());
singleServerConfig.setRetryInterval(singleConfig.getRetryInterval());
singleServerConfig.setSslEnableEndpointIdentification(redisSchemeConfig.getSslEnable());
if (redisSchemeConfig.getSslKeyPath() != null) {
singleServerConfig.setSslKeystore(new URL(redisSchemeConfig.getSslKeyPath()));
}
if (redisSchemeConfig.getSslKeyPassword() != null) {
singleServerConfig.setSslKeystorePassword(redisSchemeConfig.getSslKeyPassword());
}
singleServerConfig.setSslProvider(LockCommonConstant.JDK.equalsIgnoreCase(redisSchemeConfig.getSslProvider()) ? SslProvider.JDK : SslProvider.OPENSSL);
return Redisson.create(baseConfig);
}
@Override
public boolean supports(String pattern) {
if (StrUtil.isBlank(pattern)) {
return false;
}
return ServerPattern.SINGLE.getPattern().equals(pattern);
}
}
package com.smart.hospital.common.lock.service;
import com.smart.hospital.common.lock.key.LockKey;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.List;
public abstract class AbstractRedisLockService implements LockService {
protected LockKey<String, List<String>> lockKey;
protected RedissonClient client;
private RLock lock;
public AbstractRedisLockService(LockKey<String, List<String>> lockKey, RedissonClient client) {
this.lockKey = lockKey;
this.client = client;
}
@Override
public void lock() throws Exception {
this.lock = this.client.getFairLock(this.lockKey.getKey().get(0));
if (this.lockKey.getLeaseTime() == -1 && this.lockKey.getWaitTime() == -1) {
lock.lock();
return;
}
if (this.lockKey.getLeaseTime() != -1 && this.lockKey.getWaitTime() == -1) {
this.lock.lock(this.lockKey.getLeaseTime(), this.lockKey.getTimeUnit());
return;
}
if (this.lockKey.getLeaseTime() != -1 && this.lockKey.getWaitTime() != -1) {
boolean isLock = this.lock.tryLock(this.lockKey.getWaitTime(), this.lockKey.getLeaseTime(), this.lockKey.getTimeUnit());
if (!isLock) {
throw new IllegalStateException("加锁失败");
}
return;
}
this.lock.lock();
}
@Override
public void release() {
this.lock.forceUnlock();
}
}
package com.smart.hospital.common.lock.service;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public class LockProviderManager implements LockServiceManager {
private List<LockServiceProvider> providers;
private RedissonClient redissonClient;
private CuratorFramework zkClient;
public LockProviderManager(List<LockServiceProvider> providers, RedissonClient redissonClient, CuratorFramework zkClient) {
this.providers = providers;
this.redissonClient = redissonClient;
this.zkClient = zkClient;
}
@Override
public LockService findLockService(LockKey<String, List<String>> lockKey) {
if (providers != null && providers.size() > 0) {
for (LockServiceProvider provider : getProviders()) {
if (!provider.supports(lockKey.getLockScheme(), lockKey.getLockType())) {
continue;
}
return provider.getLockService(zkClient, redissonClient, lockKey);
}
}
return null;
}
public List<LockServiceProvider> getProviders() {
return providers;
}
}
package com.smart.hospital.common.lock.service;
/**
* 锁处理服务接口
*/
public interface LockService {
/**
* 加锁
*
* @throws Exception
*/
void lock() throws Exception;
/**
* 解锁
*/
void release();
}
package com.smart.hospital.common.lock.service;
import com.smart.hospital.common.lock.key.LockKey;
import java.util.List;
public interface LockServiceManager {
/**
* @param lockKey
* @return
*/
LockService findLockService(LockKey<String, List<String>> lockKey);
}
package com.smart.hospital.common.lock.service.impl.redis;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.AbstractRedisLockService;
import org.redisson.api.RedissonClient;
import java.util.List;
public class RedisFairRedisLockService extends AbstractRedisLockService {
public RedisFairRedisLockService(LockKey<String, List<String>> lockKey, RedissonClient client) {
super(lockKey, client);
}
@Override
public void lock() throws Exception {
super.lock();
}
@Override
public void release() {
super.release();
}
}
package com.smart.hospital.common.lock.service.impl.redis;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.AbstractRedisLockService;
import org.redisson.RedissonMultiLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.List;
public class RedisMultiRedisLockService extends AbstractRedisLockService {
private RedissonMultiLock lock;
public RedisMultiRedisLockService(LockKey<String, List<String>> lockKey, RedissonClient client) {
super(lockKey, client);
}
@Override
public void lock() throws Exception {
RLock[] lockList = new RLock[lockKey.getKey().size()];
for (int i = 0; i < lockKey.getKey().size(); i++) {
lockList[i] = client.getLock(lockKey.getKey().get(i));
}
lock = new RedissonMultiLock(lockList);
if (lockKey.getLeaseTime() == -1 && lockKey.getWaitTime() == -1) {
lock.lock();
return;
}
if (lockKey.getLeaseTime() != -1 && lockKey.getWaitTime() == -1) {
lock.lock(lockKey.getLeaseTime(), lockKey.getTimeUnit());
return;
}
if (lockKey.getLeaseTime() != -1 && lockKey.getWaitTime() != -1) {
boolean isLock = lock.tryLock(lockKey.getWaitTime(), lockKey.getLeaseTime(), lockKey.getTimeUnit());
if (!isLock) {
throw new IllegalStateException("加锁失败");
}
return;
}
lock.lock();
}
@Override
public void release() {
lock.unlock();
}
}
package com.smart.hospital.common.lock.service.impl.redis;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.AbstractRedisLockService;
import org.redisson.api.RedissonClient;
import java.util.List;
/**
* Redis可重入锁
*/
public class ReentrantRedisLockService extends AbstractRedisLockService {
public ReentrantRedisLockService(LockKey<String, List<String>> lockKey, RedissonClient client) {
super(lockKey, client);
}
@Override
public void lock() throws Exception {
super.lock();
}
@Override
public void release() {
super.release();
}
}
package com.smart.hospital.common.lock.service.impl.zookeeper;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMultiLock;
import java.util.List;
public class ZookeeperMultiZkLockService implements LockService {
private CuratorFramework zkClient;
private LockKey<String, List<String>> lockKey;
private InterProcessMultiLock lock;
public ZookeeperMultiZkLockService(CuratorFramework zkClient, LockKey<String, List<String>> lockKey) {
this.zkClient = zkClient;
this.lockKey = lockKey;
}
@Override
public void lock() throws Exception {
lock = new InterProcessMultiLock(zkClient, this.lockKey.getLockPath());
boolean success = lock.acquire(lockKey.getWaitTime(), lockKey.getTimeUnit());
if (!success) {
throw new IllegalArgumentException("加锁失败");
}
}
@Override
public void release() {
try {
if (lock.isAcquiredInThisProcess()) {
lock.release();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.smart.hospital.common.lock.service.provider;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public interface LockServiceProvider {
/**
* 获取锁
*
* @return
*/
LockService getLockService(CuratorFramework zkClient, RedissonClient client, LockKey<String, List<String>> lockKey);
/**
* 是否支持
*
* @param scheme
* @param lockType
* @return
*/
boolean supports(LockScheme scheme, LockType lockType);
}
package com.smart.hospital.common.lock.service.provider.redis;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import com.smart.hospital.common.lock.service.impl.redis.RedisFairRedisLockService;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public class RedisFairLockServiceProvider implements LockServiceProvider {
@Override
public LockService getLockService(CuratorFramework zkClient, RedissonClient client, LockKey<String, List<String>> lockKey) {
return new RedisFairRedisLockService(lockKey, client);
}
@Override
public boolean supports(LockScheme scheme, LockType lockType) {
return LockScheme.REDIS == scheme && LockType.FAIR == lockType;
}
}
package com.smart.hospital.common.lock.service.provider.redis;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import com.smart.hospital.common.lock.service.impl.redis.RedisMultiRedisLockService;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public class RedisMultiLockServiceProvider implements LockServiceProvider {
@Override
public LockService getLockService(CuratorFramework zkClient, RedissonClient client, LockKey<String, List<String>> lockKey) {
return new RedisMultiRedisLockService(lockKey, client);
}
@Override
public boolean supports(LockScheme scheme, LockType lockType) {
return LockScheme.REDIS == scheme && LockType.MULTI == lockType;
}
}
package com.smart.hospital.common.lock.service.provider.redis;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import com.smart.hospital.common.lock.service.impl.redis.ReentrantRedisLockService;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public class RedisReentrantLockServiceProvider implements LockServiceProvider {
@Override
public LockService getLockService(CuratorFramework zkClient, RedissonClient client, LockKey<String, List<String>> lockKey) {
return new ReentrantRedisLockService(lockKey, client);
}
@Override
public boolean supports(LockScheme scheme, LockType lockType) {
return LockScheme.REDIS == scheme && LockType.REENTRANT == lockType;
}
}
package com.smart.hospital.common.lock.service.provider.zookeeper;
import com.smart.hospital.common.lock.enums.LockScheme;
import com.smart.hospital.common.lock.enums.LockType;
import com.smart.hospital.common.lock.key.LockKey;
import com.smart.hospital.common.lock.service.LockService;
import com.smart.hospital.common.lock.service.impl.zookeeper.ZookeeperMultiZkLockService;
import com.smart.hospital.common.lock.service.provider.LockServiceProvider;
import org.apache.curator.framework.CuratorFramework;
import org.redisson.api.RedissonClient;
import java.util.List;
public class ZookeeperMultiZkLockServiceProvider implements LockServiceProvider {
@Override
public LockService getLockService(CuratorFramework zkClient, RedissonClient client, LockKey<String, List<String>> lockKey) {
return new ZookeeperMultiZkLockService(zkClient, lockKey);
}
@Override
public boolean supports(LockScheme scheme, LockType lockType) {
return scheme == LockScheme.ZOOKEEPER && lockType == LockType.MULTI;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.smart.hospital.common.lock.LockAutoConfiguration
spring:
lock:
lock-scheme: redis ## redis or zookeeper
pattern: single ## 单机或者集群模式
## 下面是使用reids 单机模式的配置
redis:
client-name: ladlee:lock
single-server:
address: 127.0.0.1
password: 123456 ## 没有密码则不需要这一行
database: 0
...@@ -12,4 +12,11 @@ ...@@ -12,4 +12,11 @@
<artifactId>smart-hospital-pay</artifactId> <artifactId>smart-hospital-pay</artifactId>
<description>支付/订单模块</description> <description>支付/订单模块</description>
<dependencies>
<dependency>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-common-core</artifactId>
</dependency>
</dependencies>
</project> </project>
\ No newline at end of file
...@@ -81,11 +81,6 @@ ...@@ -81,11 +81,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
</dependency> </dependency>
<!--分布式锁组件-->
<dependency>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-common-lock</artifactId>
</dependency>
<!--MQ组件--> <!--MQ组件-->
<dependency> <dependency>
<groupId>com.smart.hospital</groupId> <groupId>com.smart.hospital</groupId>
......
...@@ -92,11 +92,6 @@ ...@@ -92,11 +92,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
</dependency> </dependency>
<!--分布式锁组件-->
<dependency>
<groupId>com.smart.hospital</groupId>
<artifactId>smart-common-lock</artifactId>
</dependency>
<!--MQ组件--> <!--MQ组件-->
<dependency> <dependency>
<groupId>com.smart.hospital</groupId> <groupId>com.smart.hospital</groupId>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment