Feature-Toggle для компонентов Spring

У меня есть приложение Spring Boot с множеством аннотированных компонентов @Component, @Controller, @RestController. Есть около 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


person Marcel    schedule 24.08.2016    source источник
comment
Это большая боль. В моей компании нам разрешено выпускать недоработанный код в производство, если мы можем гарантировать, что он не будет вызываться. Итак, несмотря на то, что Spring соединил все вместе, действительно ли это имеет значение? Единственным другим вариантом является if/else, который создает технический долг еще до того, как он будет использован.   -  person Andrew S    schedule 24.08.2016
comment
Весенние профили? docs.spring.io/spring- boot/docs/current/reference/html/ Вы можете аннотировать классы только для определенных профилей. Активные профили могут быть установлены при запуске сервера.   -  person Alan Hay    schedule 24.08.2016
comment
Не-Spring библиотека ff4j.org.   -  person Alan Hay    schedule 24.08.2016


Ответы (4)


Вы можете использовать @ConditionalOnProperty аннотация:

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

Условно включенный bean-компонент — null при отключении

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

@Autowired(required=false)
private Feature1 feature1;

Если условный компонент является контроллером, вам не нужно будет его автоматически подключать, поскольку контроллер обычно не вводится. Если условный bean-компонент внедрен, вы получите No qualifying bean of type [xxx.Feature1], когда он не включен, поэтому вам необходимо автоматически связать его с помощью required=false. Тогда он останется null.

Условно включенные и отключенные компоненты

Если bean-компонент Feature1 внедрен в другие компоненты, вы можете внедрить его с помощью 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

Другой вариант — активировать бины через профили spring: @Profile("feature1"). Однако все включенные функции должны быть перечислены в одном свойстве spring.profiles.active=feature1, feature2..., поэтому я считаю, что это не то, что вам нужно.

person alexbt    schedule 24.08.2016

Попробуйте посмотреть УсловноеВыражение

и, возможно, это должно работать

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

FF4J — это платформа для реализации шаблона переключения функций. Он предлагает стартер spring-boot и позволяет включать или отключать spring компонентов во время выполнения через специальную веб-консоль. С помощью использования AOP это позволяет динамически вводить правильные bean-компоненты на основе состояний признаков. Он не добавляет и не удаляет компонент из контекста Spring.

person Cédrick Lunven    schedule 29.08.2016