@Autowired Spring @Component with @ConditionalOnProperty

时间:2017-05-19 16:16:45

标签: spring autowired featuretoggle

我可以使用@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,说“没有类型'功能'的限定bean可用:预计至少有1个bean可以作为autowire候选”。

我知道我可以通过@Configuration类来实现这一点,该类根据属性选择@Bean。但是当我这样做时,每次添加功能切换时都必须添加一个新的Configuration类,并且这些Configuration类将非常相似:

@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 个答案:

答案 0 :(得分:1)

我按照this guide做了你要做的事情。第一步是写一个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;
}

您可以使用@PropertySource注释将featuretoggles.properties添加到环境中。