Spring中能否自定义扩展@ConditionalOn系列注解实现条件配置复用
Spring自定义功能开关注解实现方案
完全可以通过Spring的组合注解特性封装自定义条件注解,避免重复编写@ConditionalOnExpression表达式,同时满足DRY原则和编译时检查的要求。
1. 封装自定义条件注解
如果你的条件逻辑可以用简单的SpEL表达式实现,可以直接复用@ConditionalOnExpression封装自定义注解:
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented // 填入你之前重复使用的条件表达式,示例为配置项app.feature.rest-enabled为true时生效,默认关闭 @ConditionalOnExpression("${app.feature.rest-enabled:false}") public @interface ConditionalOnRest { }
按照相同方式可以快速定义其他功能的条件注解:
@ConditionalOnRestAdmin:对应REST管理后台功能@ConditionalOnIndex:对应索引处理功能@ConditionalOnArchive:对应归档处理功能@ConditionalOnQueueProcessing:对应队列消费功能
2. 业务组件上直接使用自定义注解
替换之前每个组件上重复编写的@ConditionalOnExpression注解,直接使用自定义注解即可:
示例REST接口控制器:
@RestController @ConditionalOnRest public class BusinessRestController { // 接口实现逻辑 }
示例队列消费组件:
@Component @ConditionalOnQueueProcessing public class OrderQueueConsumer { // 队列消费逻辑 }
3. 不同部署节点配置开关
部署时仅需要在对应节点的配置文件中开启需要的功能开关即可,不需要的功能对应的Bean不会被Spring初始化,不会占用资源、启动多余线程:
- REST服务节点配置:
app.feature.rest-enabled=true - 管理后台节点配置:
app.feature.rest-admin-enabled=true - 索引处理节点配置:
app.feature.index-enabled=true - 归档处理节点配置:
app.feature.archive-enabled=true - 队列消费节点配置:
app.feature.queue-processing-enabled=true
进阶优化:完全自定义Condition实现
如果你的条件逻辑比较复杂,不想使用SpEL表达式,还可以通过自定义Spring Condition实现类的方式封装,完全避免SpEL写错的风险,支持编译时检查:
// 自定义条件逻辑实现类 import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class RestFeatureCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 可在此实现任意复杂的判断逻辑,比如多配置项组合判断、环境校验等 return context.getEnvironment() .getProperty("app.feature.rest-enabled", Boolean.class, false); } }
对应的自定义注解:
import org.springframework.context.annotation.Conditional; import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(RestFeatureCondition.class) public @interface ConditionalOnRest { }
这种方式的条件逻辑完全由Java代码实现,IDE可以做语法检查,完全避免拼写错误,更适合复杂的多特性开关场景。
内容的提问来源于stack exchange,提问作者user2076898。
相关产品推荐
相关产品推荐

