Spring Boot 扩展之自定义 Condition 条件注解
在实际开发中,我们经常会遇到需要根据某些条件动态创建或不创建某个 Bean 的场景。Spring 框架提供了强大的条件注解机制,允许我们在特定条件下决定是否创建 Bean。比如 ConditionalOnProperty。 但是有时候不太符号我们的要求。本文将详细介绍如何在 Spring Boot 中自定义条件注解,并通过一个具体的示例来演示其使用方法。
定义注解
首先,我们需要创建一个自定义的条件注解。这个注解将使用 @Conditional 注解来指定我们的条件类。
java
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(RateLimitTypeCondition.class)
public @interface RateLimitTypeConditionOnProperty {
String name() default "";
String[] havingValue() default {};
}
定义注解匹配规则
接下来,我们需要实现 Condition 接口,并在 matches 方法中编写我们的条件逻辑。
java
public class RateLimitTypeCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(RateLimitTypeConditionOnProperty.class.getName());
String propertyName = (String) annotationAttributes.get("name");
String[] values = (String[])annotationAttributes.get("havingValue");
if (values.length == 0) {
return false;
}
String propertyValue = context.getEnvironment().getProperty(propertyName).toLowerCase();
if (propertyValue != null) {
for (String value : values) {
if (propertyValue.contains(value.toLowerCase())) {
return true;
}
}
}
return false;
}
}
使用方式
java
public interface RateLimitService {
boolean tryAcquire();
}
@Slf4j
@Component
@RateLimitTypeConditionOnProperty(name = "limit.type",havingValue = {"distribute"})
public class DistributeRateLimitService implements RateLimitService {
@Override
public boolean tryAcquire() {
log.info("distribute rate limit");
return false;
}
}
@Component
@RateLimitTypeConditionOnProperty(name = "limit.type",havingValue = {"local"})
@Slf4j
public class LocalRateLimitService implements RateLimitService {
@Override
public boolean tryAcquire() {
log.info("local tryAcquire");
return false;
}
}
limit:
type: local,distribute
- 注意演示这里注入了两个 RateLimitService 实现类的 bean, 在使用的时候需要注意具体要使用那个, 这里不做演示
总结
自定义 Condition 注解,核心就 2 步:
(1)定义一个条件注解
(2)定义一个条件的校验规则