在 spring 引导中将 @Conditional 添加到现有的 spring 注释

Adding @Conditional to an existing spring annotation in spring boot


我有一个使用现有 spring 注释 (@EnableResourceServer) 的应用程序。我希望仅当特定 属性 值不为 false 时才启用此特定注释。 为此,我创建了一个元注释并在其上应用了 @ConditionalOnProperty :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
@EnableResourceServer
public @interface EnableCustomResourceSecurity {
}

在我的应用程序中,我现在使用 @EnableCustomResourceSecurity,例如:

@EnableCustomResourceSecurity
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
    }

}

如果 属性 缺失或为真,一切正常,但是当我将 属性 更改为 custom.resource.enabled=false 时,出现以下异常:

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

我尝试将此注释放在其他几个地方,并注意到当此注释的条件表达式失败时,在此之后的任何注释也会停止处理。

实现我想要做的事情的正确方法是什么?

您的注释 @EnableCustomResourceSecurity 具有元注释 @ConditionalOnProperty。虽然它 看起来 好像 enables/disables @EnableResourceServer 注释,但它 实际上 enables/disables 你的 MyApplication bean 作为一个整体。就好像你会写:

@SpringBootApplication
@ConditionalOnProperty(...)
@EnableResourceServer
public class MyApplication {

为避免这种情况,只需创建一个空的 SomeConfiguration class 并使用您的自定义注释对其进行注释:

@Configuration
@EnableCustomResourceSecurity
public class SomeConfiguration {}

而不是将其添加到您的 MyApplication class。

我会建议,您甚至不需要自定义注释,只需 Michiel 提到的空配置即可。反过来,此配置还将导入 @EnableResourceServer 注释。

@Configuration
@EnableResourceServer
@ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
public class ResourceServerConfig {
    public ResourceServerConfig() {
        System.out.println("initializing ResourceServerConfig ...");
    }
}

如果要基于注解进行控制,可以在自定义注解中引入相同的配置如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ResourceServerConfig.class)
public @interface EnableCustomResourceSecurity {
}