@Autowired Spring @Component с @ConditionalOnProperty

Могу ли я использовать @Autowired Spring 4.x @Components с @ConditionalOnProperty для выбора реализаций Feature на основе файла 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, говоря: «Нет подходящего bean-компонента типа 'Feature', доступного: ожидается, по крайней мере, 1 bean-компонент, который квалифицируется как кандидат 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();
    }

}

person Florian    schedule 19.05.2017    source источник
comment
@PropertySource используется только для @Configuration файла. Теперь он никогда не будет загружен, и ваши условия никогда не будут совпадать. Тем не менее, я бы все же выбрал класс конфигурации, так как он менее волшебный и на ваш взгляд, чем все эти аннотированные компоненты.   -  person M. Deinum    schedule 19.05.2017
comment
Вы совершенно правы. Попробовал и обновил пример тем, что я изменил. К сожалению, добавление класса конфигурации не улучшает ситуацию. Образец выше по-прежнему не подключается. Что я пока не мог выяснить, так это то, что @Component вообще не работает с @ConditionalOnProperty, или у меня просто все еще есть ошибка, из-за которой не удается загрузить файл свойств. К сожалению, Spring на самом деле не дает для этого значимого вывода журнала.   -  person Florian    schedule 19.05.2017


Ответы (1)


Я сделал то, что вы пытаетесь сделать, следуя этому руководству. Первым шагом было написать _1 _...

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.

person Paul    schedule 19.05.2017
comment
Сначала мы думали, что мы неправильно поняли друг друга. Но попробовал еще раз, и это действительно решило проблему. Спасибо! - person Florian; 20.05.2017