6

我有一个带有很多 @Component、@Controller、@RestController 注释组件的 Spring Boot 应用程序。我想分别切换大约 20 种不同的功能。重要的是可以在不重建项目的情况下切换功能(重新启动就可以了)。我认为 Spring 配置将是一个不错的方法。

我可以像这样想象一个配置(yml):

myApplication:
  features:
    feature1: true
    feature2: false
    featureX: ...

主要问题是我不想在所有地方都使用 if 块。我宁愿完全禁用这些组件。例如,一个 @RestController 甚至应该被加载并且它不应该注册它的路径。我目前正在寻找这样的东西:

@Component
@EnabledIf("myApplication.features.feature1")  // <- something like this
public class Feature1{
   // ...
}

有这样的功能吗?有没有一种简单的方法可以自己实现?还是有另一种功能切换的最佳实践?

顺便说一句:Spring Boot 版本:1.3.4

4

4 回答 4

7

您可以使用@ConditionalOnProperty注释:

@Component
@ConditionalOnProperty(prefix = "myApplication.features", name = "feature1")
public class Feature1{
   // ...
}
于 2016-08-24T14:35:01.743 回答
6

有条件地启用 bean - 禁用时为空

@Component
@ConditionalOnProperty(prefix = "myApplication.features", name = "feature1", havingValue="true")
public class Feature1 {
    //...
}

@Autowired(required=false)
private Feature1 feature1;

如果条件 bean 是控制器,则不需要自动装配它,因为控制器通常不会被注入。如果条件 bean 被注入,当它未启用时你会得到一个No qualifying bean of type [xxx.Feature1],这就是为什么你需要使用required=false. 然后它将保留null

条件启用和禁用 bean

如果 Feature1 bean 被注入到其他组件中,您可以使用required=false或定义在禁用该特性时返回的 bean 来注入它:

@Component
@ConditionalOnProperty(prefix = "myApplication.features", name = "feature1", havingValue="true")
public class EnabledFeature1 implements Feature1{
    //...
}

@Component
@ConditionalOnProperty(prefix = "myApplication.features", name = "feature1", havingValue="false")
public class DisabledFeature1 implements Feature1{
    //...
}

@Autowired
private Feature1 feature1;

条件启用和禁用 bean - Spring Config

@Configuration
public class Feature1Configuration{
    @Bean
    @ConditionalOnProperty(prefix = "myApplication.features", name = "feature1", havingValue="true")
    public Feature1 enabledFeature1(){
        return new EnabledFeature1();
    }

    @Bean
    @ConditionalOnProperty(prefix = "myApplication.features", name = "feature1", havingValue="false")
    public Feature1 disabledFeature1(){
        return new DisabledFeature1();
    }
}

@Autowired
private Feature1 feature1;

弹簧型材

另一种选择是通过 spring 配置文件激活 bean @Profile("feature1"):. 但是,所有启用的功能都必须列在一个属性spring.profiles.active=feature1, feature2...中,所以我相信这不是你想要的。

于 2016-08-24T17:15:23.203 回答
1

尝试查看ConditionalOnExpression

也许这应该工作

@Component
@ConditionalOnExpression("${myApplication.controller.feature1:false}")  // <- something like this
public class Feature1{
   // ...
}
于 2016-08-24T14:19:12.520 回答
1

FF4J是一个实现 Feature Toggle 模式的框架。它提出了一个spring-boot 启动器,并允许通过专用的 Web 控制台在运行时启用或禁用 spring 组件。通过使用 AOP,它允许根据功能状态动态注入正确的 bean。它不会在 spring 上下文中添加或删除 bean。

于 2016-08-29T15:34:09.020 回答