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

4 ответа

Решение

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

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

Бин с условным включением - ноль при отключении

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

@Autowired(required=false)
private Feature1 feature1;

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

Бины с условным включением и отключением

Если компонент 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;

Бины с условным включением и отключением - 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;

Весенние профили

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

Попробуйте посмотреть на ConditionalOnExpression

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

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

FF4J - это фреймворк для реализации шаблона Feature Toggle. Он предлагает стартер с пружинной загрузкой и позволяет включать или отключать пружинные компоненты во время выполнения через специальную веб-консоль. Использование AOP позволяет динамически вводить правильные bean-компоненты в зависимости от состояния объекта. Он не добавляет и не удаляет компонент из контекста весны.

Другие вопросы по тегам