我可以将 @ConditionalProperty 与我的自定义注释一起使用以避免重复配置吗?

Can I use @ConditionalProperty with my custom annotation to avoid repeating configuration?

我想使用 @OnConditional*family 注释将我的 Spring 启动应用程序的代码从逻辑上划分为几个“功能”。

我发现自己重复了很多代码,例如:

@ConditionalOnProperty( prefix = "pib2.war.features.", value = "hello", matchIfMissing = false )
@RestController
public class HelloController {
...
}

为了便于维护,我想定义元注释,这样我就可以创建某种“功能切换”,例如:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnProperty( prefix = "pib2.war.features" )
public @interface FeatureToggle {

    @AliasFor(annotation = ConditionalOnProperty.class )
    String[] value() default { };

    @AliasFor(annotation = ConditionalOnProperty.class )
    String[] name() default { };
}

这样我的代码就变成了:

@FeatureToggle( "hello" )
@RestController
public class HelloController {
...
}

但这似乎不起作用:OnPropertyCondition 评估代码忽略了 @Aliased 字段,它只是说名称为空:

...
Caused by: java.lang.IllegalStateException: The name or value attribute of @ConditionalOnProperty must be specified
    at org.springframework.util.Assert.state(Assert.java:73)
    at org.springframework.boot.autoconfigure.condition.OnPropertyCondition$Spec.getNames(OnPropertyCondition.java:129)
    at org.springframework.boot.autoconfigure.condition.OnPropertyCondition$Spec.<init>(OnPropertyCondition.java:122)
    at org.springframework.boot.autoconfigure.condition.OnPropertyCondition.determineOutcome(OnPropertyCondition.java:88)
    at org.springframework.boot.autoconfigure.condition.OnPropertyCondition.getMatchOutcome(OnPropertyCondition.java:55)
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
    ... 90 common frames omitted

所以我想不可能创建这些快捷元注释?我的配置错了吗?我应该编写自己的条件评估程序,例如“OnPropertyCondition”吗?

如果您想编写自己的条件,您应该实施 org.springframework.context.annotation.Condition

这就是 @Profile 通过定义实现 Condition 接口的 ProfileCondition class 的工作方式:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {

    /**
     * The set of profiles for which the annotated component should be registered.
     */
    String[] value();

}