@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的主要内容,如果未能解决你的问题,请参考以下文章