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-компоненты в зависимости от состояния объекта. Он не добавляет и не удаляет компонент из контекста весны.