【问题标题】:Feature-Toggle for Spring componentsSpring 组件的功能切换
【发布时间】:2016-12-31 17:14:18
【问题描述】:

我有一个带有很多 @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

【问题讨论】:

  • 这是一个很大的痛苦。在我的公司,只要我们能保证它不会被调用,我们就可以将半生不熟的代码发布到生产环境中。因此,即使 Spring 将所有内容连接在一起,这真的很重要吗?唯一的其他选项是 if/else,它甚至在使用之前就产生了技术债务。
  • 弹簧型材? docs.spring.io/spring-boot/docs/current/reference/html/… 您可以将类注释为仅适用于某些配置文件。可以在服务器启动时设置活动配置文件。
  • 非弹簧 ff4j.org 库。

标签: java spring spring-boot featuretoggle


【解决方案1】:

你可以使用@ConditionalOnProperty注解:

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

【讨论】:

    【解决方案2】:

    有条件地启用 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... 中列出,所以我相信这不是您想要的。

    【讨论】:

      【解决方案3】:

      试试看ConditionalOnExpression

      也许这应该可行

      @Component
      @ConditionalOnExpression("${myApplication.controller.feature1:false}")  // <- something like this
      public class Feature1{
         // ...
      }
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2020-03-23
          • 1970-01-01
          • 1970-01-01
          • 2017-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-09
          • 2014-11-17
          相关资源
          最近更新 更多