Skip to content

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)定义一个条件的校验规则

Released under the MIT License.