可以通过Spring配置文件选择@PropertySources吗?

Eme*_*gia 39 spring

我有一个Spring 3.1 @Configuration需要一个属性foo来构建一个bean.属性是在属性中定义的,defaults.propertiesoverrides.properties如果应用程序具有活动的overrideSpring配置文件,则可以由属性覆盖.

没有覆盖,代码看起来像这样,并且工作......

@Configuration
@PropertySource("classpath:defaults.properties")
public class MyConfiguration {

    @Autowired
    private Environment environment;

    @Bean
    public Bean bean() {
        ...
        // this.environment.getRequiredProperty("foo");
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我想一个@PropertySource用于classpath:overrides.properties对队伍@Profile("overrides").有没有人对如何实现这一点有任何想法?我考虑过的一些选项是重复的@Configuration,但这会违反DRY或程序化操作ConfigurableEnvironment,但我不确定environment.getPropertySources.addFirst()调用的去向.

如果我直接注入属性@Value,但是在我使用EnvironmentgetRequiredProperty()方法时,将以下内容放在XML配置中.

<context:property-placeholder ignore-unresolvable="true" location="classpath:defaults.properties"/>

<beans profile="overrides">
    <context:property-placeholder ignore-unresolvable="true" order="0"
                                  location="classpath:overrides.properties"/>
</beans>
Run Code Online (Sandbox Code Playgroud)

更新

如果您现在尝试执行此操作,请查看Spring Boot的YAML支持,尤其是"使用YAML而不是属性"部分.那里的配置文件支持会使这个问题没有实际意义,但还没有@PropertySource支持.

Dav*_*ess 46

@PropertySource在静态内部类中添加覆盖.不幸的是,您必须一起指定所有属性源,这意味着创建"默认"配置文件作为"覆盖"的替代.

@Configuration
public class MyConfiguration
{
    @Configuration
    @Profile("default")
    @PropertySource("classpath:defaults.properties")
    static class Defaults
    { }

    @Configuration
    @Profile("override")
    @PropertySource({"classpath:defaults.properties", "classpath:overrides.properties"})
    static class Overrides
    {
        // nothing needed here if you are only overriding property values
    }

    @Autowired
    private Environment environment;

    @Bean
    public Bean bean() {
        ...
        // this.environment.getRequiredProperty("foo");
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 无法理解为什么这个答案得到了这么多的赞成.对配置文件名称进行硬编码与配置文件无关.是不是有类似的方式让你通过'spring.profiles.active'参数指定配置文件? (5认同)

Spi*_*lle 12

我建议定义两个文件,其中第二个是可选的,以配置文件为后缀:

@Configuration
@PropertySources({
        @PropertySource("classpath:/myconfig.properties"),
        @PropertySource(value = "classpath:/myconfig-${spring.profiles.active}.properties", ignoreResourceNotFound = true)
})
public class MyConfigurationFile {

    @Value("${my.prop1}")
    private String prop1;

    @Value("${my.prop2}")
    private String prop2;

}
Run Code Online (Sandbox Code Playgroud)

  • 如果您有多个配置文件,则此操作会失败(例如,我有活动配置文件=“dev,mock” (7认同)

Seb*_*ber 9

你可以做:

  <context:property-placeholder location="classpath:${spring.profiles.active}.properties" />
Run Code Online (Sandbox Code Playgroud)

编辑:如果您需要更高级的东西,可以在应用程序启动时注册PropertySources.

web.xml中

  <context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.xxx.core.spring.properties.PropertySourcesApplicationContextInitializer</param-value>
  </context-param>
Run Code Online (Sandbox Code Playgroud)

你创建的文件:

public class PropertySourcesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

  private static final Logger LOGGER = LoggerFactory.getLogger(PropertySourcesApplicationContextInitializer.class);

  @Override
  public void initialize(ConfigurableApplicationContext applicationContext) {
    LOGGER.info("Adding some additional property sources");
    String[] profiles = applicationContext.getEnvironment().getActiveProfiles()
    // ... Add property sources according to selected spring profile 
    // (note there already are some property sources registered, system properties etc)
    applicationContext.getEnvironment().getPropertySources().addLast(myPropertySource);
  }

}
Run Code Online (Sandbox Code Playgroud)

完成后,您只需添加上下文:

<context:property-placeholder/>
Run Code Online (Sandbox Code Playgroud)

我无法真正回答您关于多个配置文件的问题,但我想您在这样的初始化程序上激活它们,并且您可以在配置文件激活期间注册相应的PropertySource项目.

  • 这不是假设只有一个配置文件处于活动状态吗? (3认同)
  • 您可以使用`applicationContext.getEnvironment()访问已解析的活动配置文件列表作为数组.getActiveProfiles()` (2认同)

Bij*_*men 5

除了您建议的艾默生之外,我想不出任何其他方法,即在@Configuration带有注释的单独文件中定义此 bean @Profile

@Configuration
@Profile("override")
@PropertySource("classpath:override.properties")
public class OverriddenConfig {

    @Autowired
    private Environment environment;

    @Bean
    public Bean bean() {
        //if..
    }
}
Run Code Online (Sandbox Code Playgroud)


whi*_*row 5

如果您需要支持多个配置文件,您可以执行以下操作:

@Configuration
public class Config {

    @Configuration
    @Profile("default")
    @PropertySource("classpath:application.properties")
    static class DefaultProperties {
    }

    @Configuration
    @Profile("!default")
    @PropertySource({"classpath:application.properties", "classpath:application-${spring.profiles.active}.properties"})
    static class NonDefaultProperties {
    }
}
Run Code Online (Sandbox Code Playgroud)

这样您就不需要为每个配置文件定义静态配置类。感谢大卫·哈克尼斯为我指明了正确的方向。