通过@Import覆盖Spring @PropertySource

bra*_*ter 13 spring properties

test=default在类DefaultConfig中有一个属性,我使用@PropertySource注释使它们可用.

@Configuration
@PropertySource("classpath:default.properties")
public class DefaultConfig {}
Run Code Online (Sandbox Code Playgroud)

然后我希望能够覆盖到test=override,这是在OverrideConfig类的不同属性文件中,所以我再次使用@PropertySource.

@Configuration
@Import(DefaultConfig.class)
@PropertySource("classpath:override.properties")
public class OverrideConfig {}
Run Code Online (Sandbox Code Playgroud)

我配置一个测试来证明它的工作原理.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={OverrideConfig.class})
public class TestPropertyOverride {

    @Autowired
    private Environment env;

    @Test
    public void propertyIsOverridden() {
        assertEquals("override", env.getProperty("test"));
    }

}
Run Code Online (Sandbox Code Playgroud)

当然,它不是.

org.junit.ComparisonFailure: expected:<[override]> but was:<[default]>

最大化调试,我可以看到发生了什么:

StandardEnvironment:107 - Adding [class path resource [default.properties]] PropertySource with lowest search precedence
StandardEnvironment:107 - Adding [class path resource [override.properties]] PropertySource with lowest search precedence
Run Code Online (Sandbox Code Playgroud)

它似乎倒退了.我是否犯了一个简单的错误或者误解了这个错误,或者您是否希望@ Import-ed类中的@PropertySource定义的属性被@ Import-ing类中的@PropertySource定义的属性覆盖?

kup*_*fic 6

以下是Helder Sousa的解决方案,作为对OP创建的JIRA问题的评论:

[T]使用嵌套配置可以实现spring xml中的行为(一个xml导入另一个xml):

@Configuration
@PropertySource("classpath:default.properties")
public class DefaultConfig {}
Run Code Online (Sandbox Code Playgroud)
@Configuration
@PropertySource("classpath:override.properties")
public class OverrideConfig {

    @Configuration
    @Import(DefaultConfig.class)
    static class InnerConfiguration {}

}
Run Code Online (Sandbox Code Playgroud)

使用此设置,将按正确的顺序收集属性.


Rob*_*bin 1

我目前在 Spring 3.1 中遇到类似的情况,但我使用不同的方法来覆盖属性,因为@PropertySource不支持可选属性文件:

@Configuration
@PropertySource("classpath:default.properties")
public class BaseConfig {

  @Inject
  private ApplicationContext context;

  @PostConstruct
  public void init() throws IOException {
    Resource runtimeProps = context.getResource("classpath:override.properties");
    if (runtimeProps.exists()) {
      MutablePropertySources sources = ((ConfigurableApplicationContext) context).getEnvironment().getPropertySources();
      sources.addFirst(new ResourcePropertySource(runtimeProps));
    }
  }
...
Run Code Online (Sandbox Code Playgroud)

除了正常 bean 依赖项规定的顺序之外,似乎@Import不会导致任何特定的实例化顺序。@Configuration强制执行此类顺序的一种方法是将基础@Configuration实例本身作为依赖项注入。你能尝试一下吗:

@Configuration
@Import(DefaultConfig.class)
@PropertySource("classpath:override.properties")
public class OverrideConfig {

  @Inject
  private DefaultConfig defaultConfig;

  ...
}
Run Code Online (Sandbox Code Playgroud)

这有帮助吗?也许新的ContextHierarchy注释在这里也能有所帮助,但到目前为止我还没有尝试过这个。

  • 阿门。尽管我讨厌 XML 接线,但我确实怀念 `&lt;context:property-placeholderignore-resource-not-found="true" location="classpath:base.config,file:override.config" /&gt;` (3认同)