Spring:从文件读取属性为什么执行Condition :: match

时间:2016-06-30 11:10:52

标签: java spring

我想根据application.properties中的标志实现条件Bean。例如:

// application.properties
service=foobar

我们的想法是让不同的服务实现可配置,假设我在Spring中为这个服务设置了一个中央配置类:

@Configuration
@Import({ServiceA.class, ServiceB.class, ...})
public class ServiceConfiguration {
    ...
}

可能的服务实现看起来像

@Configuration
public class ServiceA implements Condition {

    @Bean
    @Conditional(ServiceA.class)
    public Service service() {
        Service a = ...
        return a; 
    }

    @Override
    public boolean matches(
            ConditionContext conditionContext, 
            AnnotatedTypeMetadata annotatedTypeMetadata) {
        // getProperty will alsways return null for some reason
        return conditionContext
                .getEnvironment()
                 .getProperty("service")
                  .equals("ServiceA");
    }

    // This will be null anyways
    @Value("${service}")
    private String confService;
}

由于实现Condition的类(这里只是同一个类ServiceA)将通过默认构造函数@Value初始化 - 注入将无效。但是,根据我的理解getProperty()应该返回正确的值。我究竟做错了什么?如何在此时访问应用程序属性?

1 个答案:

答案 0 :(得分:2)

我找到了肮脏的工作场所",我真的不喜欢这个解决方案,但它解决了这个问题。如上所述here @PropertySource解决了问题(我没有在发布之前尝试过这个问题,因为它不是一个有效的答案)。

@Configuration
@PropertySource(value="file:config/application.properties")
public class ServiceA implements Condition {

    @Bean
    @Conditional(ServiceA.class)
    public Service service() {
        Service a = ...
        return a; 
    }

    @Override
    public boolean matches(
            ConditionContext conditionContext, 
            AnnotatedTypeMetadata annotatedTypeMetadata) {
        // Will work now
        return conditionContext
                .getEnvironment()
                 .getProperty("service")
                  .equals("ServiceA");
    }    

}

虽然这有效但我不喜欢它有几个原因:

  • 每次实现我都有代码冗余(给出配置文件的路径)
  • 拥有多个配置文件时,它非常难以维护
    • 示例:加载default.properties< -then加载和覆盖的行为 - > customer.properties 不再工作了(尽管这应该可以使用@PropertySources来解决,另一方面会增加代码冗余)