@Autowired Spring @Component с @ConditionalOnProperty
Могу ли я использовать @Autowired
Spring 4.x @Component
с @ConditionalOnProperty
выбрать реализации компонента на основе файла featuretoggles.properties?
public class Controller {
@Autowired
private Feature feature;
}
@Component
@ConditionalOnProperty(name = "b", havingValue = "off")
public class A implements Feature {
}
@Component
@ConditionalOnProperty(name = "b", havingValue = "on")
public class B implements Feature {
}
@Configuration
@PropertySource("classpath:featuretoggles.properties")
public class SomeRandomConfig {
}
С файлом src/main/resources/featuretoggles.properties:
b = on
(То, что имя переключателя "b" и имя класса "B" совпадают; это не моя цель, чтобы они были равны, у переключателя может быть любое имя.)
Это не удается автоматически подключить feature
в Controller
с UnsatisfiedDependencyException
, говоря: "Нет подходящего бина типа" Feature ": ожидается как минимум 1 бин, который считается кандидатом autowire".
Я знаю, что могу понять это с @Configuration
класс, который выбирает @Bean
в зависимости от имущества. Но когда я делаю это, мне приходится добавлять новый класс конфигурации каждый раз, когда я добавляю функцию переключения, и эти классы конфигурации будут очень похожи:
@Configuration
@PropertySource("classpath:featuretoggles.properties")
public class FeatureConfig {
@Bean
@ConditionalOnProperty(name = "b", havingValue = "on")
public Feature useB() {
return new B();
}
@Bean
@ConditionalOnProperty(name = "b", havingValue = "off")
public Feature useA() {
return new A();
}
}
1 ответ
Я сделал то, что вы пытаетесь сделать, следуя этому руководству. Первым шагом было написать Condition
...
public class OnEnvironmentPropertyCondition implements Condition
{
@Override
public boolean matches(ConditionContext ctx, AnnotatedTypeMetadata meta)
{
Environment env = ctx.getEnvironment();
Map<String, Object> attr = meta.getAnnotationAttributes(
ConditionalOnEnvProperty.class.getName());
boolean shouldPropExist = (Boolean)attr.get("exists");
String prop = (String)attr.get("value");
boolean doesPropExist = env.getProperty(prop) != null;
// doesPropExist shouldPropExist result
// true true true
// true false false
// false true false
// true false true
return doesPropExist == shouldPropExist;
}
}
... затем аннотация с использованием этого условия.
/*
* Condition returns true if myprop exists:
* @ConditionalOnEnvProperty("myprop")
*
* Condition returns true if myprop does not exist
* @ConditionalOnEnvProperty(value="myprop", exists=false)
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnEnvironmentPropertyCondition.class)
public @interface ConditionalOnEnvProperty
{
public String value();
public boolean exists() default true;
}
Можете добавить featuretoggles.properties
в среду с аннотацией @PropertySource.