Spring Boot Starter 机制:如何编写自定义 Starter
原创作者:[您的名字]
阅读时长:约 15-20 分钟
难度:中级-高级
关键词:Spring Boot、Starter、自动配置、自定义启动器、最佳实践
📖 前言
Spring Boot 的核心优势之一就是"约定优于配置",而 Starter 机制正是这一理念的完美体现。通过引入各种 Starter,我们只需在 pom.xml 中添加一个依赖,就能自动获得完整的配置和功能集成。
但你有没有想过:这些 Starter 是如何工作的?我们能否编写自己的 Starter? 本文将深入 Spring Boot 3.x 源码,剖析自动配置原理,并手把手教你编写一个生产级别的自定义 Starter。
🎯 目录
- [Spring Boot Starter 原理深度剖析](#Spring Boot Starter 原理深度剖析)
- 自动配置核心机制
- [编写自定义 Starter 的完整流程](#编写自定义 Starter 的完整流程)
- [生产级 Starter 最佳实践](#生产级 Starter 最佳实践)
- [实战案例:Redis 分布式锁 Starter](#实战案例:Redis 分布式锁 Starter)
- 常见问题与解决方案
- 总结与展望
1. Spring Boot Starter 原理深度剖析
1.1 什么是 Starter?
Spring Boot Starter 是一组便捷的依赖描述符,你可以将其包含在应用中。通过获得一组你需要的依赖项(如 Web、测试、数据访问等),你就不需要一个个地复制粘贴依赖配置。
官方 Starter 命名规范: - 官方:spring-boot-starter-* - 第三方:*-spring-boot-starter
graph LR
A[应用引入 Starter] --> B[自动配置触发]
B --> C[条件注解评估]
C --> D[Bean 实例化]
D --> E[功能可用]
style A fill:#e1f5fe
style B fill:#fff9c4
style C fill:#f1f8e9
style D fill:#fce4ec
style E fill:#e8f5e9
1.2 Spring Boot 3.x 自动配置源码剖析
让我们深入 Spring Boot 3.3.x 源码,看看自动配置是如何工作的。
核心注解:@SpringBootApplication
java
#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}// Spring Boot 3.3.5`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@Target(ElementType.TYPE)`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@Retention(RetentionPolicy.RUNTIME)`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@Documented`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@Inherited`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@SpringBootConfiguration // 标记为配置类`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@EnableAutoConfiguration // 启用自动配置(核心)`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
} @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}public @interface SpringBootApplication {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
} // ... 省略其他代码`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/SpringBootApplication.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 标记为配置类
@EnableAutoConfiguration // 启用自动配置(核心)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ... 省略其他代码
}}
自动配置导入:@EnableAutoConfiguration
java
#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}// Spring Boot 3.3.5`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} @Override`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} public String[] selectImports(AnnotationMetadata annotationMetadata) {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} if (!isEnabled(annotationMetadata)) {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} return NO_IMPORTS;`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} }`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 1. 加载自动配置候选类`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} AutoConfigurationEntry autoConfigurationEntry = `
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} getAutoConfigurationEntry(annotationMetadata);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 2. 返回需要导入的配置类全限定名`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} }`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} if (!isEnabled(annotationMetadata)) {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} return EMPTY_ENTRY;`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} }`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 3. 获取注解属性`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} AnnotationAttributes attributes = getAttributes(annotationMetadata);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 4. 从 META-INF/spring.factories 或 `
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 加载候选配置类`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} List<String> configurations = getCandidateConfigurations(`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} annotationMetadata, attributes);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 5. 去重`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} configurations = removeDuplicates(configurations);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 6. 排除指定的配置类`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} Set<String> exclusions = getExclusions(annotationMetadata, attributes);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} checkExcludedClasses(configurations, exclusions);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} configurations.removeAll(exclusions);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 7. 过滤掉不满足条件的配置(重要!)`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} configurations = getConfigurationClassFilter().filter(configurations);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} // 8. 触发自动配置导入事件`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} fireAutoConfigurationImportEvents(configurations, exclusions);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} return new AutoConfigurationEntry(configurations, exclusions);`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
} }`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 1. 加载自动配置候选类
AutoConfigurationEntry autoConfigurationEntry =
getAutoConfigurationEntry(annotationMetadata);
// 2. 返回需要导入的配置类全限定名
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 3. 获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 4. 从 META-INF/spring.factories 或
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 加载候选配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
// 5. 去重
configurations = removeDuplicates(configurations);
// 6. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 7. 过滤掉不满足条件的配置(重要!)
configurations = getConfigurationClassFilter().filter(configurations);
// 8. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}}
关键变化:Spring Boot 2.7 vs 3.x
| 特性 | Spring Boot 2.7 | Spring Boot 3.x |
|---|---|---|
| 配置文件位置 | META-INF/spring.factories |
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
| 文件格式 | Properties 格式(键值对) | 纯文本(每行一个全限定类名) |
| 兼容性 | 向后兼容 spring.factories |
优先使用新格式,降级兼容旧格式 |
| 加载性能 | 单文件加载所有配置 | 分散加载,按需加载 |
自动配置加载流程
sequenceDiagram
participant App as 应用启动
participant A as @EnableAutoConfiguration
participant L as AutoConfigurationImportSelector
participant F as 配置文件加载器
participant C as 条件注解处理器
participant B as Bean 容器
App->>A: 读取注解
A->>L: 调用 selectImports()
L->>F: 加载 AutoConfiguration.imports
F-->>L: 返回候选配置类列表
L->>L: 去重、排除、过滤
L->>C: 评估 @ConditionalOnClass 等条件
C-->>L: 返回满足条件的配置
L-->>A: 返回最终配置类列表
A->>B: 注册为 @Configuration
B->>B: 实例化 Bean
2. 自动配置核心机制
2.1 条件注解体系
Spring Boot 提供了一组强大的条件注解,用于控制 Bean 的创建时机。
核心条件注解对比
| 注解 | 作用 | 示例场景 |
|---|---|---|
| @ConditionalOnClass | classpath 中存在指定类 | 当 Redis 存在时配置 RedisTemplate |
| @ConditionalOnMissingClass | classpath 中不存在指定类 | 当没有其他数据源时配置默认数据源 |
| @ConditionalOnBean | 容器中存在指定 Bean | 当已有 DataSource 时配置 JPA |
| @ConditionalOnMissingBean | 容器中不存在指定 Bean | 提供默认实现,允许用户覆盖 |
| @ConditionalOnProperty | 配置文件中属性匹配 | 通过开关控制功能启用 |
| @ConditionalOnResource | 指定资源存在 | 当配置文件存在时加载配置 |
| @ConditionalOnWebApplication | Web 应用环境 | 仅在 Web 应用中配置 Servlet |
| @ConditionalOnNotWebApplication | 非 Web 应用环境 | 仅在非 Web 应用中配置调度任务 |
条件注解源码示例
java
#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}// Spring Boot 3.3.5`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}@Target({ ElementType.TYPE, ElementType.METHOD })`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}@Retention(RetentionPolicy.RUNTIME)`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}@Documented`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}@Conditional(OnClassCondition.class) // 条件判断逻辑`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}public @interface ConditionalOnClass {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} Class<?>[] value() default {}; // 使用 Class 对象`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} String[] name() default {}; // 使用全限定类名`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}}`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}// 条件判断逻辑`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}class OnClassCondition extends FilteringSpringBootCondition {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} @Override`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} AutoConfigurationMetadata autoConfigurationMetadata) {`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} // 1. 检查 ClassLoader 是否能加载指定类`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} // 2. 返回匹配结果`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
} }`
`#// Spring Boot 3.3.5
// 文件路径:org/springframework/boot/autoconfigure/condition/ConditionalOnClass.java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 条件判断逻辑
public @interface ConditionalOnClass {
Class<?>[] value() default {}; // 使用 Class 对象
String[] name() default {}; // 使用全限定类名
}
// 条件判断逻辑
class OnClassCondition extends FilteringSpringBootCondition {
@Override
public ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// 1. 检查 ClassLoader 是否能加载指定类
// 2. 返回匹配结果
}
}}
实际应用示例
java
#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}@Configuration`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}@ConditionalOnProperty(`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} prefix = "spring.redis", // 配置前缀`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} name = "enabled", // 配置项`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} havingValue = "true", // 期望值`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} matchIfMissing = true // 默认启用`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
})`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}public class RedisAutoConfiguration {`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} @Bean`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} @ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} public RedisConnectionFactory redisConnectionFactory() {`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} return new LettuceConnectionFactory();`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} }`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} @Bean`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} @ConditionalOnMissingBean`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} public RedisTemplate<Object, Object> redisTemplate(`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} RedisConnectionFactory redisConnectionFactory) {`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} RedisTemplate<Object, Object> template = new RedisTemplate<>();`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} template.setConnectionFactory(redisConnectionFactory);`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} return template;`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
} }`
`#@Configuration
@ConditionalOnClass(RedisOperations.class) // 当 Redis 类存在时
@ConditionalOnMissingBean(name = "redisTemplate") // 当用户未自定义时
@ConditionalOnProperty(
prefix = "spring.redis", // 配置前缀
name = "enabled", // 配置项
havingValue = "true", // 期望值
matchIfMissing = true // 默认启用
)
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器中没有 RedisConnectionFactory 时
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}}
2.2 自动配置排序
Spring Boot 使用 @AutoConfigurationOrder 和 @AutoConfigureBefore/After 控制配置类的加载顺序。
java
#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
}// 示例:数据源自动配置`
`#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
}@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级`
`#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
}@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前`
`#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
}public class DataSourceAutoConfiguration {`
`#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
} // ...`
`#// 示例:数据源自动配置
@AutoConfigurationOrder(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
@AutoConfigurationBefore(MyBatisAutoConfiguration.class) // 在 MyBatis 之前
public class DataSourceAutoConfiguration {
// ...
}}
加载优先级: 1. @AutoConfigurationOrder 数值越小,优先级越高 2. @AutoConfigureBefore 指定在某个配置之前加载 3. @AutoConfigureAfter 指定在某个配置之后加载
3. 编写自定义 Starter 的完整流程
3.1 项目结构设计
一个标准的 Starter 项目应包含以下模块:
custom-spring-boot-starter/
├── custom-spring-boot-starter/ # 自动配置模块(核心)
│ ├── pom.xml
│ └── src/main/java/
│ ├── com/example/custom/
│ │ ├── CustomProperties.java # 配置属性类
│ │ ├── CustomAutoConfiguration.java # 自动配置类
│ │ └── CustomService.java # 核心服务类
│ └── resources/
│ └── META-INF/
│ └── spring/
│ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
└── custom-spring-boot-starter-example/ # 示例模块(可选)
└── ...
3.2 创建项目
模块 1:custom-spring-boot-starter
pom.xml 配置:
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project><?xml version="1.0" encoding="UTF-8"?>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project><project xmlns="http://maven.apache.org/POM/4.0.0"
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> https://maven.apache.org/xsd/maven-4.0.0.xsd">
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <modelVersion>4.0.0</modelVersion>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <parent>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <groupId>org.springframework.boot</groupId>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <artifactId>spring-boot-starter-parent</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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <version>3.3.5</version>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <relativePath/>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </parent>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <groupId>com.example</groupId>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <artifactId>custom-spring-boot-starter</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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <version>1.0.0</version>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <name>Custom Spring Boot Starter</name>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <description>Custom starter for demo purposes</description>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <properties>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <java.version>17</java.version>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </properties>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <dependencies>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <!-- Spring Boot 自动配置依赖(不包含 starter) -->
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <groupId>org.springframework.boot</groupId>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <artifactId>spring-boot-autoconfigure</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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <!-- 配置处理器(生成元数据,IDE 提示) -->
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <groupId>org.springframework.boot</groupId>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <artifactId>spring-boot-configuration-processor</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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <optional>true</optional>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <!-- Lombok(可选,简化代码) -->
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <groupId>org.projectlombok</groupId>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <artifactId>lombok</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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> <optional>true</optional>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </dependency>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project> </dependencies>
#<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>Custom Spring Boot Starter</name>
<description>Custom starter for demo purposes</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot 自动配置依赖(不包含 starter) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置处理器(生成元数据,IDE 提示) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok(可选,简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project></project>
步骤 1:创建配置属性类
java
#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}package com.example.custom;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}import lombok.Data;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}import org.springframework.boot.context.properties.ConfigurationProperties;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}import org.springframework.stereotype.Component;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}/**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 自定义配置属性类`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 配置前缀:custom.demo`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}@Data`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}@Component`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}public class CustomProperties {`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 是否启用自定义功能`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private boolean enabled = true; // 默认值`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 自定义名称`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private String name = "Default";`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 自定义最大数量`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private int maxCount = 100;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 高级配置`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private Advanced advanced = new Advanced();`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} @Data`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} public static class Advanced {`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 超时时间(毫秒)`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private long timeout = 5000L;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} `
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} /**`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} * 是否启用缓存`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} */`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} private boolean cacheEnabled = false;`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
} }`
`#package com.example.custom;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 自定义配置属性类
* 配置前缀:custom.demo
*/
@Data
@Component
@ConfigurationProperties(prefix = "custom.demo") // 配置文件中的前缀
public class CustomProperties {
/**
* 是否启用自定义功能
*/
private boolean enabled = true; // 默认值
/**
* 自定义名称
*/
private String name = "Default";
/**
* 自定义最大数量
*/
private int maxCount = 100;
/**
* 高级配置
*/
private Advanced advanced = new Advanced();
@Data
public static class Advanced {
/**
* 超时时间(毫秒)
*/
private long timeout = 5000L;
/**
* 是否启用缓存
*/
private boolean cacheEnabled = false;
}
}}
步骤 2:创建核心服务类
java
#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}package com.example.custom;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}import lombok.extern.slf4j.Slf4j;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}import org.springframework.beans.factory.annotation.Autowired;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}/**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} * 自定义核心服务类`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}@Slf4j`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}public class CustomService {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} private final CustomProperties properties;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} // 构造器注入(推荐)`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} @Autowired`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} public CustomService(CustomProperties properties) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} this.properties = properties;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} log.info("CustomService 初始化完成,配置:{}", properties);`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} /**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} * 执行自定义逻辑`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} public String process(String input) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} if (!properties.isEnabled()) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} log.warn("自定义功能未启用");`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} return "功能未启用";`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} log.info("处理输入:{}, 使用配置:name={}, maxCount={}", `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} input, properties.getName(), properties.getMaxCount());`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} return String.format("处理结果:[%s] - %s", `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} properties.getName(), input);`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} /**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} * 获取当前配置信息`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} public CustomProperties getProperties() {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} return properties;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义核心服务类
*/
@Slf4j
public class CustomService {
private final CustomProperties properties;
// 构造器注入(推荐)
@Autowired
public CustomService(CustomProperties properties) {
this.properties = properties;
log.info("CustomService 初始化完成,配置:{}", properties);
}
/**
* 执行自定义逻辑
*/
public String process(String input) {
if (!properties.isEnabled()) {
log.warn("自定义功能未启用");
return "功能未启用";
}
log.info("处理输入:{}, 使用配置:name={}, maxCount={}",
input, properties.getName(), properties.getMaxCount());
return String.format("处理结果:[%s] - %s",
properties.getName(), input);
}
/**
* 获取当前配置信息
*/
public CustomProperties getProperties() {
return properties;
}
}}
步骤 3:创建自动配置类
java
#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}package com.example.custom;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import lombok.extern.slf4j.Slf4j;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.boot.autoconfigure.AutoConfiguration;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.boot.context.properties.EnableConfigurationProperties;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}import org.springframework.context.annotation.Bean;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}/**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * 自定义自动配置类`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * 这是 Starter 的核心,负责创建和注册 Bean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}@Slf4j`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}@ConditionalOnProperty(`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} prefix = "custom.demo",`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} name = "enabled",`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} havingValue = "true",`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} matchIfMissing = true // 默认启用`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
})`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}public class CustomAutoConfiguration {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} /**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * 创建 CustomService Bean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * @ConditionalOnMissingBean:允许用户自定义覆盖`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} @Bean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} @ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} public CustomService customService(CustomProperties properties) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} log.info("正在创建 CustomService Bean...");`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} return new CustomService(properties);`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} /**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * 可选:创建其他辅助 Bean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} @Bean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} @ConditionalOnMissingBean`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} @ConditionalOnProperty(`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} prefix = "custom.demo.advanced",`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} name = "cache-enabled",`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} havingValue = "true"`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} )`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} public CustomCacheManager customCacheManager(CustomProperties properties) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} log.info("启用自定义缓存管理器,超时时间:{}ms", `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} properties.getAdvanced().getTimeout());`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} return new CustomCacheManager(properties.getAdvanced().getTimeout());`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} /**`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} * 简单的缓存管理器示例`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} */`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} public static class CustomCacheManager {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} private final long timeout;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} public CustomCacheManager(long timeout) {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} this.timeout = timeout;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} `
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} public long getTimeout() {`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} return timeout;`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
} }`
`#package com.example.custom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;
/**
* 自定义自动配置类
* 这是 Starter 的核心,负责创建和注册 Bean
*/
@Slf4j
@AutoConfiguration // Spring Boot 3.x 使用此注解替代 @Configuration
@ConditionalOnClass(CustomService.class) // 当 CustomService 类存在时
@EnableConfigurationProperties(CustomProperties.class) // 启用配置属性
@ConditionalOnProperty(
prefix = "custom.demo",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用
)
public class CustomAutoConfiguration {
/**
* 创建 CustomService Bean
* @ConditionalOnMissingBean:允许用户自定义覆盖
*/
@Bean
@ConditionalOnMissingBean // 当容器中没有 CustomService 时才创建
public CustomService customService(CustomProperties properties) {
log.info("正在创建 CustomService Bean...");
return new CustomService(properties);
}
/**
* 可选:创建其他辅助 Bean
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "custom.demo.advanced",
name = "cache-enabled",
havingValue = "true"
)
public CustomCacheManager customCacheManager(CustomProperties properties) {
log.info("启用自定义缓存管理器,超时时间:{}ms",
properties.getAdvanced().getTimeout());
return new CustomCacheManager(properties.getAdvanced().getTimeout());
}
/**
* 简单的缓存管理器示例
*/
public static class CustomCacheManager {
private final long timeout;
public CustomCacheManager(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}
}}
步骤 4:创建自动配置导入文件
Spring Boot 3.x 方式(推荐):
创建文件:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.custom.CustomAutoConfiguration
Spring Boot 2.7 兼容方式(降级):
创建文件:src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.custom.CustomAutoConfiguration
3.3 编写单元测试
java
#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}package com.example.custom;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}import org.junit.jupiter.api.Test;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}import org.springframework.beans.factory.annotation.Autowired;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}import org.springframework.boot.test.context.SpringBootTest;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}import org.springframework.test.context.TestPropertySource;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}import static org.assertj.core.api.Assertions.assertThat;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}@SpringBootTest(classes = CustomAutoConfiguration.class)`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}class CustomAutoConfigurationTest {`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} `
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} @Autowired(required = false)`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} private CustomService customService;`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} `
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} @Test`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} void testCustomServiceBeanExists() {`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} assertThat(customService).isNotNull();`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} }`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} `
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} @Test`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} @TestPropertySource(properties = {`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} "custom.demo.enabled=true",`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} "custom.demo.name=TestName"`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} })`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} void testCustomServiceProcess() {`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} String result = customService.process("test input");`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} assertThat(result).contains("TestName");`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} assertThat(result).contains("test input");`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
} }`
`#package com.example.custom;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CustomAutoConfiguration.class)
class CustomAutoConfigurationTest {
@Autowired(required = false)
private CustomService customService;
@Test
void testCustomServiceBeanExists() {
assertThat(customService).isNotNull();
}
@Test
@TestPropertySource(properties = {
"custom.demo.enabled=true",
"custom.demo.name=TestName"
})
void testCustomServiceProcess() {
String result = customService.process("test input");
assertThat(result).contains("TestName");
assertThat(result).contains("test input");
}
}}
3.4 编写配置元数据(可选但推荐)
创建文件:src/main/resources/META-INF/spring-configuration-metadata.json
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
}{
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "groups": [
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "com.example.custom.CustomProperties",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "sourceType": "com.example.custom.CustomProperties",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "自定义功能配置"
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} }
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} ],
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "properties": [
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo.enabled",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "java.lang.Boolean",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "是否启用自定义功能",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "defaultValue": true
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} },
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo.name",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "java.lang.String",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "自定义名称",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "defaultValue": "Default"
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} },
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo.max-count",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "java.lang.Integer",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "自定义最大数量",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "defaultValue": 100
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} },
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo.advanced.timeout",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "java.lang.Long",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "超时时间(毫秒)",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "defaultValue": 5000
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} },
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} {
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "name": "custom.demo.advanced.cache-enabled",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "type": "java.lang.Boolean",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "description": "是否启用缓存",
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "defaultValue": false
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} }
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} ],
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
} "hints": []
#{
"groups": [
{
"name": "custom.demo",
"type": "com.example.custom.CustomProperties",
"sourceType": "com.example.custom.CustomProperties",
"description": "自定义功能配置"
}
],
"properties": [
{
"name": "custom.demo.enabled",
"type": "java.lang.Boolean",
"description": "是否启用自定义功能",
"defaultValue": true
},
{
"name": "custom.demo.name",
"type": "java.lang.String",
"description": "自定义名称",
"defaultValue": "Default"
},
{
"name": "custom.demo.max-count",
"type": "java.lang.Integer",
"description": "自定义最大数量",
"defaultValue": 100
},
{
"name": "custom.demo.advanced.timeout",
"type": "java.lang.Long",
"description": "超时时间(毫秒)",
"defaultValue": 5000
},
{
"name": "custom.demo.advanced.cache-enabled",
"type": "java.lang.Boolean",
"description": "是否启用缓存",
"defaultValue": false
}
],
"hints": []
}}
作用: 在 IDE(如 IntelliJ IDEA、VS Code)中提供自动补全和提示。
4. 生产级 Starter 最佳实践
4.1 命名规范
| 类型 | 命名规范 | 示例 |
|---|---|---|
| 官方 Starter | spring-boot-starter-* |
spring-boot-starter-web |
| 第三方 Starter | *-spring-boot-starter |
mybatis-spring-boot-starter |
| 自动配置类 | *AutoConfiguration |
RedisAutoConfiguration |
| 配置属性类 | *Properties |
RedisProperties |
4.2 版本管理
方案 1:使用 Spring Boot BOM
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement><dependencyManagement>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependency>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <groupId>org.springframework.boot</groupId>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <artifactId>spring-boot-dependencies</artifactId>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <version>3.3.5</version>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <type>pom</type>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <scope>import</scope>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> </dependency>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> </dependencies>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement></dependencyManagement>
方案 2:自定义 BOM
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement><dependencyManagement>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependency>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <groupId>com.example</groupId>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <artifactId>custom-spring-boot-starter-bom</artifactId>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <version>1.0.0</version>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <type>pom</type>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <scope>import</scope>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> </dependency>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> </dependencies>
#<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-spring-boot-starter-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement></dependencyManagement>
4.3 依赖管理原则
graph TD
A[Starter 依赖设计] --> B{必须依赖?}
B -->|是| C[添加为 compile 依赖]
B -->|否| D[添加为 optional 依赖]
C --> E[示例: spring-boot-autoconfigure]
D --> F[示例: Redis 驱动、Lombok]
style A fill:#e1f5fe
style E fill:#c8e6c9
style F fill:#ffccbc
规则: - compile 范围: Spring Boot 核心依赖、必须的运行时依赖 - optional 范围: 可选功能依赖(如数据库驱动) - provided 范围: 用户应用提供的依赖(如 Lombok)
4.4 配置优先级设计
java
#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
}@ConfigurationProperties(prefix = "custom.demo")`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
}public class CustomProperties {`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} `
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} // 1. 提供合理的默认值`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} private boolean enabled = true;`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} `
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} // 2. 允许用户覆盖`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} private String name = "Default";`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} `
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} // 3. 支持嵌套配置`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} private Advanced advanced = new Advanced();`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} `
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} // 4. 使用 JSR-303 校验`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} @Min(1)`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} @Max(10000)`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} private int maxCount = 100;`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} `
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} @NotNull`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
} private String requiredField;`
`#@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// 1. 提供合理的默认值
private boolean enabled = true;
// 2. 允许用户覆盖
private String name = "Default";
// 3. 支持嵌套配置
private Advanced advanced = new Advanced();
// 4. 使用 JSR-303 校验
@Min(1)
@Max(10000)
private int maxCount = 100;
@NotNull
private String requiredField;
}}
4.5 日志规范
java
#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
}@Slf4j // 使用 Lombok`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
}public class CustomService {`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} `
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} public void doSomething() {`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} // 1. 启动时记录关键信息`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} log.info("CustomService 启动,配置:{}", properties);`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} `
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} // 2. 调试时使用 debug 级别`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} log.debug("处理请求:{}", request);`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} `
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} // 3. 警告潜在问题`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} `
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} // 4. 错误时记录异常堆栈`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} log.error("处理失败", exception);`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
} }`
`#@Slf4j // 使用 Lombok
public class CustomService {
public void doSomething() {
// 1. 启动时记录关键信息
log.info("CustomService 启动,配置:{}", properties);
// 2. 调试时使用 debug 级别
log.debug("处理请求:{}", request);
// 3. 警告潜在问题
log.warn("配置项 {} 已废弃,请使用 {}", oldKey, newKey);
// 4. 错误时记录异常堆栈
log.error("处理失败", exception);
}
}}
5. 实战案例:Redis 分布式锁 Starter
5.1 需求分析
实现一个 Redis 分布式锁 Starter,支持: - 自动配置 RedisTemplate - 提供分布式锁接口 - 支持锁超时、重试 - 支持注解式声明锁
5.2 项目结构
redis-lock-spring-boot-starter/
├── redis-lock-spring-boot-starter/
│ ├── src/main/java/
│ │ └── com/example/redislock/
│ │ ├── RedisLockProperties.java # 配置属性
│ │ ├── RedisLockAutoConfiguration.java # 自动配置
│ │ ├── RedisLockService.java # 锁服务
│ │ ├── RedisLockAspect.java # AOP 切面
│ │ └── annotation/
│ │ └── RedisLock.java # 锁注解
│ └── src/main/resources/
│ └── META-INF/spring/
│ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
5.3 配置属性类
java
#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}package com.example.redislock;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}import lombok.Data;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}import org.springframework.boot.context.properties.ConfigurationProperties;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}@Data`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}@ConfigurationProperties(prefix = "redis.lock")`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}public class RedisLockProperties {`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} `
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} /**`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} * 锁前缀`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} */`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} private String keyPrefix = "lock:";`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} `
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} /**`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} * 默认超时时间(毫秒)`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} */`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} private long defaultTimeout = 30000;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} `
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} /**`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} * 获取锁的重试间隔(毫秒)`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} */`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} private long retryInterval = 100;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} `
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} /**`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} * 最大重试次数(-1 表示无限重试)`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} */`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} private int maxRetries = 3;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} `
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} /**`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} * 是否启用注解支持`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} */`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
} private boolean annotationEnabled = true;`
`#package com.example.redislock;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "redis.lock")
public class RedisLockProperties {
/**
* 锁前缀
*/
private String keyPrefix = "lock:";
/**
* 默认超时时间(毫秒)
*/
private long defaultTimeout = 30000;
/**
* 获取锁的重试间隔(毫秒)
*/
private long retryInterval = 100;
/**
* 最大重试次数(-1 表示无限重试)
*/
private int maxRetries = 3;
/**
* 是否启用注解支持
*/
private boolean annotationEnabled = true;
}}
5.4 核心锁服务
java
#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}package com.example.redislock;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}import lombok.extern.slf4j.Slf4j;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}import org.springframework.data.redis.core.RedisTemplate;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}import org.springframework.data.redis.core.script.DefaultRedisScript;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}import java.util.Collections;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}import java.util.concurrent.TimeUnit;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}/**`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * Redis 分布式锁服务`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * 基于 Redis SET NX EX 命令实现`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} */`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}@Slf4j`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}public class RedisLockService {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} private final RedisTemplate<String, Object> redisTemplate;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} private final RedisLockProperties properties;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} // Lua 脚本:确保解锁的原子性`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} private static final String UNLOCK_SCRIPT = `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} "if redis.call('get', KEYS[1]) == ARGV[1] then " +`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} " return redis.call('del', KEYS[1]) " +`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} "else " +`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} " return 0 " +`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} "end";`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} public RedisLockService(RedisTemplate<String, Object> redisTemplate,`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} RedisLockProperties properties) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} this.redisTemplate = redisTemplate;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} this.properties = properties;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} /**`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * 尝试获取锁`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * @param lockKey 锁的键`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * @param requestId 请求标识(用于解锁时验证)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * @param timeout 超时时间(毫秒)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * @return 是否获取成功`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} */`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} public boolean tryLock(String lockKey, String requestId, long timeout) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} String fullKey = properties.getKeyPrefix() + lockKey;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} try {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} Boolean result = redisTemplate.opsForValue().setIfAbsent(`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} fullKey, // 键`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} requestId, // 值(用于解锁验证)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} timeout, // 超时时间`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} TimeUnit.MILLISECONDS`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} );`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return Boolean.TRUE.equals(result);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} } catch (Exception e) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.error("获取锁异常:{}", fullKey, e);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return false;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} /**`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * 阻塞式获取锁(带重试)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} */`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} public boolean lock(String lockKey, String requestId, long timeout) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} String fullKey = properties.getKeyPrefix() + lockKey;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} long startTime = System.currentTimeMillis();`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} int retries = 0;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} while (true) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} // 尝试获取锁`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} if (tryLock(lockKey, requestId, timeout)) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.info("成功获取锁:{}", fullKey);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return true;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} // 检查是否超过最大重试次数`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} if (properties.getMaxRetries() != -1 && `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} retries >= properties.getMaxRetries()) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.warn("获取锁失败,达到最大重试次数:{}", fullKey);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return false;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} // 检查是否超时`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} long elapsed = System.currentTimeMillis() - startTime;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} if (elapsed > timeout) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.warn("获取锁超时:{}", fullKey);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return false;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} // 等待后重试`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} try {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} retries++;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} } catch (InterruptedException e) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} Thread.currentThread().interrupt();`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return false;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} /**`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} * 释放锁(使用 Lua 脚本保证原子性)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} */`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} public boolean unlock(String lockKey, String requestId) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} String fullKey = properties.getKeyPrefix() + lockKey;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} try {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} Long result = redisTemplate.execute(`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} script,`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} Collections.singletonList(fullKey),`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} requestId`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} );`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} boolean success = result != null && result == 1L;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.info("释放锁:{}, 结果:{}", fullKey, success);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return success;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} } catch (Exception e) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} log.error("释放锁异常:{}", fullKey, e);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} return false;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* Redis 分布式锁服务
* 基于 Redis SET NX EX 命令实现
*/
@Slf4j
public class RedisLockService {
private final RedisTemplate<String, Object> redisTemplate;
private final RedisLockProperties properties;
// Lua 脚本:确保解锁的原子性
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
public RedisLockService(RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
this.redisTemplate = redisTemplate;
this.properties = properties;
}
/**
* 尝试获取锁
*
* @param lockKey 锁的键
* @param requestId 请求标识(用于解锁时验证)
* @param timeout 超时时间(毫秒)
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
Boolean result = redisTemplate.opsForValue().setIfAbsent(
fullKey, // 键
requestId, // 值(用于解锁验证)
timeout, // 超时时间
TimeUnit.MILLISECONDS
);
log.debug("尝试获取锁:{}, 结果:{}", fullKey, result);
return Boolean.TRUE.equals(result);
} catch (Exception e) {
log.error("获取锁异常:{}", fullKey, e);
return false;
}
}
/**
* 阻塞式获取锁(带重试)
*/
public boolean lock(String lockKey, String requestId, long timeout) {
String fullKey = properties.getKeyPrefix() + lockKey;
long startTime = System.currentTimeMillis();
int retries = 0;
while (true) {
// 尝试获取锁
if (tryLock(lockKey, requestId, timeout)) {
log.info("成功获取锁:{}", fullKey);
return true;
}
// 检查是否超过最大重试次数
if (properties.getMaxRetries() != -1 &&
retries >= properties.getMaxRetries()) {
log.warn("获取锁失败,达到最大重试次数:{}", fullKey);
return false;
}
// 检查是否超时
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
log.warn("获取锁超时:{}", fullKey);
return false;
}
// 等待后重试
try {
TimeUnit.MILLISECONDS.sleep(properties.getRetryInterval());
retries++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
}
/**
* 释放锁(使用 Lua 脚本保证原子性)
*/
public boolean unlock(String lockKey, String requestId) {
String fullKey = properties.getKeyPrefix() + lockKey;
try {
DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
Long result = redisTemplate.execute(
script,
Collections.singletonList(fullKey),
requestId
);
boolean success = result != null && result == 1L;
log.info("释放锁:{}, 结果:{}", fullKey, success);
return success;
} catch (Exception e) {
log.error("释放锁异常:{}", fullKey, e);
return false;
}
}
}}
5.5 注解式锁支持
锁注解:
java
#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}package com.example.redislock.annotation;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}import java.lang.annotation.*;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}import java.util.concurrent.TimeUnit;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}@Target(ElementType.METHOD)`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}@Retention(RetentionPolicy.RUNTIME)`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}@Documented`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}public @interface RedisLock {`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} `
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} /**`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} * 锁的键(支持 SpEL 表达式)`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} * 示例:"'user:' + #userId"`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} */`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} String key();`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} `
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} /**`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} * 超时时间(默认使用配置值)`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} */`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} long timeout() default -1;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} `
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} /**`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} * 时间单位(默认毫秒)`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} */`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} TimeUnit timeUnit() default TimeUnit.MILLISECONDS;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} `
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} /**`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} * 是否阻塞等待`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} */`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
} boolean blocking() default true;`
`#userId"
*/
String key();
/**
* 超时时间(默认使用配置值)
*/
long timeout() default -1;
/**
* 时间单位(默认毫秒)
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 是否阻塞等待
*/
boolean blocking() default true;
}}
AOP 切面:
java
#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}package com.example.redislock;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import com.example.redislock.annotation.RedisLock;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import lombok.extern.slf4j.Slf4j;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.aspectj.lang.ProceedingJoinPoint;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.aspectj.lang.annotation.Around;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.aspectj.lang.annotation.Aspect;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.aspectj.lang.reflect.MethodSignature;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.beans.factory.annotation.Autowired;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.core.DefaultParameterNameDiscoverer;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.core.ParameterNameDiscoverer;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.expression.EvaluationContext;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.expression.Expression;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.expression.spel.standard.SpelExpressionParser;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.expression.spel.support.StandardEvaluationContext;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import org.springframework.stereotype.Component;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import java.util.UUID;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}import java.util.concurrent.TimeUnit;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}@Slf4j`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}@Aspect`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}@Component`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}@ConditionalOnProperty(`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} prefix = "redis.lock",`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} name = "annotation-enabled",`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} havingValue = "true",`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} matchIfMissing = true`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
})`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}public class RedisLockAspect {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} @Autowired`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} private RedisLockService lockService;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} @Autowired`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} private RedisLockProperties properties;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} private final SpelExpressionParser parser = new SpelExpressionParser();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} private final ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} @Around("@annotation(redisLock)")`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 1. 解析锁键(支持 SpEL 表达式)`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} String lockKey = parseKey(redisLock.key(), joinPoint);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 2. 生成唯一请求标识`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} String requestId = UUID.randomUUID().toString();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 3. 确定超时时间`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} long timeout = redisLock.timeout() != -1 ? `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} redisLock.timeUnit().toMillis(redisLock.timeout()) : `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} properties.getDefaultTimeout();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 4. 尝试获取锁`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} boolean locked;`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} if (redisLock.blocking()) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} locked = lockService.lock(lockKey, requestId, timeout);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} } else {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} locked = lockService.tryLock(lockKey, requestId, timeout);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} if (!locked) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} log.warn("获取锁失败:{}", lockKey);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} throw new RuntimeException("获取分布式锁失败:" + lockKey);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} try {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 5. 执行业务逻辑`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} log.debug("获取锁成功,执行方法:{}", lockKey);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} return joinPoint.proceed();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} } finally {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} // 6. 释放锁`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} boolean unlocked = lockService.unlock(lockKey, requestId);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} log.debug("释放锁:{}, 结果:{}", lockKey, unlocked);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} /**`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} * 解析 SpEL 表达式`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} */`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} private String parseKey(String key, ProceedingJoinPoint joinPoint) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} if (!key.contains("#")) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} return key; // 不是 SpEL 表达式,直接返回`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} MethodSignature signature = (MethodSignature) joinPoint.getSignature();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} Object[] args = joinPoint.getArgs();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} EvaluationContext context = new StandardEvaluationContext();`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} if (parameterNames != null) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} for (int i = 0; i < parameterNames.length; i++) {`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} context.setVariable(parameterNames[i], args[i]);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} `
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} Expression expression = parser.parseExpression(key);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} return expression.getValue(context, String.class);`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
} }`
`#")) {
return key; // 不是 SpEL 表达式,直接返回
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = nameDiscoverer.getParameterNames(signature.getMethod());
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
Expression expression = parser.parseExpression(key);
return expression.getValue(context, String.class);
}
}}
5.6 自动配置类
java
#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}package com.example.redislock;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import lombok.extern.slf4j.Slf4j;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.autoconfigure.AutoConfiguration;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.boot.context.properties.EnableConfigurationProperties;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.context.annotation.Bean;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}import org.springframework.data.redis.core.RedisTemplate;`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}@Slf4j`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}@EnableConfigurationProperties(RedisLockProperties.class)`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}@ConditionalOnProperty(`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} prefix = "redis.lock",`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} name = "enabled",`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} havingValue = "true",`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} matchIfMissing = true`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
})`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}public class RedisLockAutoConfiguration {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} `
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} @Bean`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} @ConditionalOnMissingBean`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} public RedisLockService redisLockService(`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} RedisTemplate<String, Object> redisTemplate,`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} RedisLockProperties properties) {`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} log.info("初始化 RedisLockService,配置:{}", properties);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} return new RedisLockService(redisTemplate, properties);`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
} }`
`#package com.example.redislock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
@AutoConfiguration(after = RedisAutoConfiguration.class) // 在 Redis 配置之后
@ConditionalOnClass(RedisTemplate.class) // 当 Redis 存在时
@EnableConfigurationProperties(RedisLockProperties.class)
@ConditionalOnProperty(
prefix = "redis.lock",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class RedisLockAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisLockService redisLockService(
RedisTemplate<String, Object> redisTemplate,
RedisLockProperties properties) {
log.info("初始化 RedisLockService,配置:{}", properties);
return new RedisLockService(redisTemplate, properties);
}
}}
5.7 配置文件
application.yml 示例:
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: trueredis:
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true lock:
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true enabled: true
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true key-prefix: "myapp:lock:"
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true default-timeout: 30000 # 30秒
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true retry-interval: 100
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true max-retries: 5
# 30秒
retry-interval: 100
max-retries: 5
annotation-enabled: true annotation-enabled: true
5.8 使用示例
编程式使用:
java
#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
}@Service`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
}public class OrderService {`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} @Autowired`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} private RedisLockService lockService;`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} public void createOrder(String orderId) {`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} String requestId = UUID.randomUUID().toString();`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} try {`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} // 获取锁`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} boolean locked = lockService.lock(`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} "order:" + orderId, // 锁键`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} requestId, // 请求标识`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} 10000 // 超时时间`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} );`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} if (!locked) {`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} throw new RuntimeException("订单创建中,请稍后重试");`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} }`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} // 执行业务逻辑`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} // ...`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} `
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} } finally {`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} // 释放锁`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} lockService.unlock("order:" + orderId, requestId);`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} }`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
} }`
`#@Service
public class OrderService {
@Autowired
private RedisLockService lockService;
public void createOrder(String orderId) {
String requestId = UUID.randomUUID().toString();
try {
// 获取锁
boolean locked = lockService.lock(
"order:" + orderId, // 锁键
requestId, // 请求标识
10000 // 超时时间
);
if (!locked) {
throw new RuntimeException("订单创建中,请稍后重试");
}
// 执行业务逻辑
// ...
} finally {
// 释放锁
lockService.unlock("order:" + orderId, requestId);
}
}
}}
注解式使用:
java
#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
}@Service`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
}public class UserService {`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} `
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} @RedisLock(key = "'user:update:' + #userId", timeout = 10, timeUnit = TimeUnit.SECONDS)`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} public void updateUser(String userId, User user) {`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} // 方法执行期间会自动加锁`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} // ...`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
} }`
`#userId", timeout = 10, timeUnit = TimeUnit.SECONDS)
public void updateUser(String userId, User user) {
// 方法执行期间会自动加锁
// ...
}
}}
6. 常见问题与解决方案
6.1 自动配置未生效
问题: Starter 依赖引入后,Bean 未自动创建。
排查步骤:
graph TD
A[自动配置未生效] --> B{检查依赖}
B -->|依赖缺失| C[添加 compile 范围依赖]
B -->|依赖正常| D{检查配置文件}
D -->|文件不存在| E[创建 AutoConfiguration.imports]
D -->|文件存在| F{检查类名}
F -->|类名错误| G[修正全限定类名]
F -->|类名正确| H{检查条件注解}
H -->|条件不满足| I[调整配置或条件]
H -->|条件满足| J[启用 DEBUG 日志]
style A fill:#ffebee
style C fill:#c8e6c9
style E fill:#c8e6c9
style G fill:#c8e6c9
style I fill:#c8e6c9
style J fill:#fff9c4
解决方案:
-
启用 DEBUG 日志:
#logging:
level:
org.springframework.boot.autoconfigure: DEBUGlogging:
#logging:
level:
org.springframework.boot.autoconfigure: DEBUG level:
#logging:
level:
org.springframework.boot.autoconfigure: DEBUG org.springframework.boot.autoconfigure: DEBUG -
查看条件评估报告:
启动时添加参数
java -jar app.jar --debug# 启动时添加参数
启动时添加参数
java -jar app.jar --debugjava -jar app.jar --debug
-
手动导入配置类:
java
#@SpringBootApplication
@Import(CustomAutoConfiguration.class) // 手动导入
public class Application {
// ...
}@SpringBootApplication`
`#@SpringBootApplication
@Import(CustomAutoConfiguration.class) // 手动导入
public class Application {
// ...
}@Import(CustomAutoConfiguration.class) // 手动导入`
`#@SpringBootApplication
@Import(CustomAutoConfiguration.class) // 手动导入
public class Application {
// ...
}public class Application {`
`#@SpringBootApplication
@Import(CustomAutoConfiguration.class) // 手动导入
public class Application {
// ...
} // ...`
`#@SpringBootApplication
@Import(CustomAutoConfiguration.class) // 手动导入
public class Application {
// ...
}}
6.2 配置属性绑定失败
问题: @ConfigurationProperties 注解的属性无法绑定值。
原因分析:
| 原因 | 解决方案 |
|---|---|
缺少 @EnableConfigurationProperties |
在配置类上添加注解 |
| 类路径不在扫描范围内 | 添加 @Component 或手动注册 |
| 配置文件路径错误 | 检查 application.yml/properties 路径 |
| 类型不匹配 | 检查配置值类型与字段类型一致性 |
解决方案:
java
#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}// 方案 1:在配置类上启用`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}@Configuration`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}@EnableConfigurationProperties(CustomProperties.class)`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}public class CustomAutoConfiguration {`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
} // ...`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}}`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}// 方案 2:在属性类上添加组件注解`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}@Component`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}@ConfigurationProperties(prefix = "custom.demo")`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}public class CustomProperties {`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
} // ...`
`#// 方案 1:在配置类上启用
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
// ...
}
// 方案 2:在属性类上添加组件注解
@Component
@ConfigurationProperties(prefix = "custom.demo")
public class CustomProperties {
// ...
}}
6.3 Bean 覆盖问题
问题: 自定义 Bean 被 Starter 的默认 Bean 覆盖。
最佳实践:
java
#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}// Starter 提供默认实现`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}@Bean`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}@ConditionalOnMissingBean // 关键:允许用户覆盖`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}public CustomService customService(CustomProperties properties) {`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} return new CustomService(properties);`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}}`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}// 用户自定义实现`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}@Configuration`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}public class UserConfiguration {`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} `
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} @Bean`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} public CustomService customService(CustomProperties properties) {`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} // 用户自定义实现会覆盖 Starter 的默认实现`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} return new UserCustomService(properties);`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
} }`
`#// Starter 提供默认实现
@Bean
@ConditionalOnMissingBean // 关键:允许用户覆盖
public CustomService customService(CustomProperties properties) {
return new CustomService(properties);
}
// 用户自定义实现
@Configuration
public class UserConfiguration {
@Bean
public CustomService customService(CustomProperties properties) {
// 用户自定义实现会覆盖 Starter 的默认实现
return new UserCustomService(properties);
}
}}
6.4 循环依赖问题
问题: Bean 之间相互依赖,启动失败。
解决方案:
java
#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案// 方案 1:使用 @Lazy 延迟加载`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案@Configuration`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案public class ConfigA {`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 `
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 @Bean`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 public ServiceA serviceA(@Lazy ServiceB serviceB) {`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 return new ServiceA(serviceB);`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 }`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案}`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案// 方案 2:使用 Setter 注入代替构造器注入`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案@Configuration`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案public class ConfigB {`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 `
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 @Bean`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 public ServiceB serviceB() {`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 ServiceB serviceB = new ServiceB();`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 // 通过 Setter 注入`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 serviceB.setServiceA(null); // 后续由 Spring 注入`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 return serviceB;`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案 }`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案}`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案// 方案 3:重构代码,消除循环依赖`
`#// 方案 1:使用 @Lazy 延迟加载
@Configuration
public class ConfigA {
@Bean
public ServiceA serviceA(@Lazy ServiceB serviceB) {
return new ServiceA(serviceB);
}
}
// 方案 2:使用 Setter 注入代替构造器注入
@Configuration
public class ConfigB {
@Bean
public ServiceB serviceB() {
ServiceB serviceB = new ServiceB();
// 通过 Setter 注入
serviceB.setServiceA(null); // 后续由 Spring 注入
return serviceB;
}
}
// 方案 3:重构代码,消除循环依赖
// 这是最根本的解决方案// 这是最根本的解决方案
6.5 版本兼容性问题
Spring Boot 2.x → 3.x 迁移注意事项:
| 变化点 | Spring Boot 2.x | Spring Boot 3.x | 迁移建议 |
|---|---|---|---|
| 配置文件 | spring.factories |
AutoConfiguration.imports |
创建新格式文件 |
| JDK 版本 | JDK 8+ | JDK 17+ | 升级到 JDK 17 |
| javax.* | javax.servlet |
jakarta.servlet |
替换包名 |
| @Conditional | 旧版条件注解 | 增强版条件注解 | 无需修改,向后兼容 |
迁移步骤:
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports# 1. 升级 JDK 到 17+
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsjava -version
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports# 2. 更新 pom.xml
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports<parent>
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports <groupId>org.springframework.boot</groupId>
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports <artifactId>spring-boot-starter-parent</artifactId>
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports <version>3.3.5</version> <!-- 从 2.7.x 升级 -->
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</parent>
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports# 3. 替换 javax 为 jakarta
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsfind . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports# 4. 创建新格式配置文件
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsmkdir -p src/main/resources/META-INF/spring
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsecho "com.example.CustomAutoConfiguration" > \
# 1. 升级 JDK 到 17+
java -version
# 2. 更新 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version> <!-- 从 2.7.x 升级 -->
</parent>
# 3. 替换 javax 为 jakarta
find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
# 4. 创建新格式配置文件
mkdir -p src/main/resources/META-INF/spring
echo "com.example.CustomAutoConfiguration" > \
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
7. 总结与展望
7.1 核心要点回顾
本文从 Spring Boot 3.x 源码出发,深入剖析了 Starter 机制的核心原理,并提供了完整的生产级 Starter 开发指南。
关键要点:
- 自动配置原理:
@EnableAutoConfiguration触发配置加载AutoConfigurationImportSelector扫描配置文件- 条件注解过滤不满足条件的配置
- 配置文件变化:
- Spring Boot 3.x 使用
AutoConfiguration.imports - 向后兼容
spring.factories
- Spring Boot 3.x 使用
- 最佳实践:
- 遵循命名规范
- 合理设计依赖范围
- 提供合理的默认值
- 使用条件注解控制 Bean 创建
- 编写完整的单元测试
7.2 技术演进趋势
timeline
title Spring Boot Starter 演进史
section Spring Boot 1.x
2014 : 引入 spring.factories<br>自动配置机制
section Spring Boot 2.x
2017 : 增强条件注解<br>引入 @ConditionalOn* 系列注解
section Spring Boot 2.7
2022 : 引入新配置文件格式<br>AutoConfiguration.imports
section Spring Boot 3.x
2023 : 默认使用新格式<br>要求 JDK 17+
section 未来趋势
2025+ : 更智能的配置推断<br>AI 辅助配置生成
7.3 实战建议
编写 Starter 的决策树:
graph TD
A[需要编写 Starter? ] --> B{功能是否通用?}
B -->|否| C[直接在项目中配置]
B -->|是| D{是否需要自动配置?}
D -->|否| E[提供普通依赖即可]
D -->|是| F{是否需要条件化?}
F -->|否| G[简单的 @Configuration]
F -->|是| H[编写完整的 Starter]
H --> I[遵循最佳实践]
I --> J[编写完整测试]
I --> K[提供详细文档]
I --> L[发布到 Maven 仓库]
style C fill:#ffcdd2
style E fill:#fff9c4
style G fill:#c8e6c9
style H fill:#b2dfdb
style I fill:#b3e5fc
7.4 进阶学习路径
- 深入源码:
- 阅读
AutoConfigurationImportSelector源码 - 研究条件注解实现原理
- 学习
ConfigurationPropertiesBinding机制
- 阅读
- 扩展功能:
- 自定义条件注解
- 实现
ApplicationContextInitializer - 开发
EnvironmentPostProcessor
- 性能优化:
- 延迟初始化配置
- 按需加载依赖
- 减少不必要的 Bean 创建
7.5 推荐资源
官方文档: - Spring Boot Auto-configuration - Spring Boot Configuration Properties
优秀开源项目: - mybatis-spring-boot-starter - 数据持久化 - spring-boot-starter-data-redis - Redis 集成 - spring-cloud-starter-openfeign - 声明式 HTTP 客户端
实战练习: 1. 编写一个日志切面 Starter 2. 实现一个邮件发送 Starter 3. 开发一个限流 Starter
🔗 附录
A. 完整项目结构
redis-lock-spring-boot-starter/
├── pom.xml
├── README.md
├── LICENSE
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/redislock/
│ │ │ ├── RedisLockProperties.java
│ │ │ ├── RedisLockAutoConfiguration.java
│ │ │ ├── RedisLockService.java
│ │ │ ├── RedisLockAspect.java
│ │ │ └── annotation/
│ │ │ └── RedisLock.java
│ │ └── resources/
│ │ ├── META-INF/
│ │ │ └── spring/
│ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── spring-configuration-metadata.json
│ └── test/
│ └── java/
│ └── com/example/redislock/
│ ├── RedisLockServiceTest.java
│ └── RedisLockAspectTest.java
└── example/
└── src/
└── main/
├── java/
│ └── com/example/demo/
│ └── DemoApplication.java
└── resources/
└── application.yml
B. Maven 仓库发布
发布到 Central:
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build><distributionManagement>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <snapshotRepository>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <id>ossrh</id>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <url>https://oss.sonatype.org/content/repositories/snapshots</url>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </snapshotRepository>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <repository>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <id>ossrh</id>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </repository>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build></distributionManagement>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build><build>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <plugins>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <!-- GPG 签名插件 -->
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <groupId>org.apache.maven.plugins</groupId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <artifactId>maven-gpg-plugin</artifactId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <version>3.1.0</version>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <id>sign-artifacts</id>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <phase>verify</phase>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goal>sign</goal>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <!-- 源码插件 -->
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <groupId>org.apache.maven.plugins</groupId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <artifactId>maven-source-plugin</artifactId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <version>3.3.0</version>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <id>attach-sources</id>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goal>jar-no-fork</goal>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <!-- Javadoc 插件 -->
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <groupId>org.apache.maven.plugins</groupId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <artifactId>maven-javadoc-plugin</artifactId>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <version>3.6.3</version>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <id>attach-javadocs</id>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> <goal>jar</goal>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </goals>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </execution>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </executions>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </plugin>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </plugins>
#<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- GPG 签名插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 源码插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build></build>
发布命令:
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release# 1. 清理并编译
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Releasemvn clean install
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release# 2. 部署到远程仓库
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Releasemvn deploy
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release# 3. 登录 Nexus 仓库进行 Release
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release# 访问:https://oss.sonatype.org/
# 1. 清理并编译
mvn clean install
# 2. 部署到远程仓库
mvn deploy
# 3. 登录 Nexus 仓库进行 Release
# 访问:https://oss.sonatype.org/
# 操作:Staging Repositories → Close → Release# 操作:Staging Repositories → Close → Release
C. 测试覆盖率配置
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin><plugin>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <groupId>org.jacoco</groupId>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <artifactId>jacoco-maven-plugin</artifactId>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <version>0.8.11</version>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <executions>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <execution>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <goals>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <goal>prepare-agent</goal>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </goals>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </execution>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <execution>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <id>report</id>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <phase>test</phase>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <goals>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <goal>report</goal>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </goals>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </execution>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </executions>
#<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin></plugin>
📝 结语
Spring Boot Starter 机制是 Spring Boot "约定优于配置"理念的完美体现。通过本文的学习,你应该掌握了:
✅ Spring Boot 3.x 自动配置的核心原理
✅ 条件注解的使用方法和最佳实践
✅ 完整的自定义 Starter 开发流程
✅ 生产级 Redis 分布式锁 Starter 实现
✅ 常见问题的排查和解决方案
记住: 编写一个好的 Starter,不仅需要技术能力,更需要对用户场景的深入理解。始终站在使用者的角度思考,提供合理默认值、清晰的配置选项和完善的文档。
希望这篇文章能帮助你更好地理解和使用 Spring Boot Starter。如果有任何问题或建议,欢迎在评论区留言讨论!
标签: Spring Boot Starter 自定义启动器 自动配置 最佳实践 Spring Boot 3.x 源码分析
作者简介: [您的简介]
发布时间: 2024-03-30
阅读量: [阅读量]
点赞数: [点赞数]