@Import 覆盖 Spring @PropertySource

Posted

技术标签:

【中文标题】@Import 覆盖 Spring @PropertySource【英文标题】:Overriding Spring @PropertySource by @Import 【发布时间】:2013-03-12 17:02:25 【问题描述】:

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

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

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

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

我配置了一个测试来证明它有效。

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

    @Autowired
    private Environment env;

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


当然不是。

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

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

【问题讨论】:

可能发生的情况是,您的OverrideConfig 类上的注释首先被评估,因此test=override,然后DefaultConfig 类被导入,它的注释被评估,test 被覆盖到default 提出问题jira.springsource.org/browse/SPR-10409 【参考方案1】:

这是Helder Sousa 的解决方案,写为a comment of the JIRA issue 由OP 创建:

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

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

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


通过此设置,属性将以正确的顺序收集。

【讨论】:

【参考方案2】:

今天 Spring 4 你可以使用这个:

@TestPropertySource(value="classpath:/config/test.properties")

这可用于使用并最终覆盖 junit 测试的属性:

@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(value="classpath:/config/test.properties")

【讨论】:

【参考方案3】:

我遇到了类似的问题,并且成功地在我的自定义配置中声明了默认属性:

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

【讨论】:

【参考方案4】:

您可以像这样强制执行属性的加载顺序:

@Configuration
@PropertySource(value="classpath:default.properties","classpath:override.properties")
public class OverrideConfig 
...

【讨论】:

【参考方案5】:

我目前在 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));
    
  
...

似乎@Import 不会导致任何特定的@Configuration 实例化顺序,除了正常的bean 依赖关系所规定的顺序。强制执行此类命令的一种方法是将基本 @Configuration 实例本身作为依赖项注入。你可以试试:

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

  @Inject
  private DefaultConfig defaultConfig;

  ...

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

【讨论】:

恐怕没用。据我所知,这种行为就是这样,除非 Spring 人员同意改变它。案例提出。 阿门。尽管我讨厌 XML 接线,但我确实想念<context:property-placeholder ignore-resource-not-found="true" location="classpath:base.config,file:override.config" />

以上是关于@Import 覆盖 Spring @PropertySource的主要内容,如果未能解决你的问题,请参考以下文章

解决import org.apache.commons.lang.StringUtils问题

以编程方式设置视图

Spring Security

Spring 注入

Spring

OC基础 代理模式