在纯Spring Framework(非Spring Boot)集成测试中,如何让PropertySourcesPlaceholderConfigurer优先搜索系统属性?
在纯Spring Framework(非Spring Boot)集成测试中,如何让PropertySourcesPlaceholderConfigurer优先搜索系统属性?
哎,这个问题我太熟了!之前在纯Spring项目里做集成测试时也踩过这个坑——默认情况下PropertySourcesPlaceholderConfigurer并不会优先用系统属性,得咱们手动调整配置才行。
首先得给你理清楚默认逻辑:Spring的Environment里默认的属性源顺序中,系统属性的优先级其实是低于配置文件这类属性源的,所以占位符解析时会先找配置文件里的值,找不到才会看系统属性。但咱们要反过来,让系统属性先被搜索。
最简单直接的办法就是自定义PropertySourcesPlaceholderConfigurer的Bean,给它设置系统属性覆盖模式:
- 首先在你的测试配置类里,定义一个静态的
PropertySourcesPlaceholderConfigurerBean方法(必须是静态的!因为它是BeanFactoryPostProcessor,Spring要在其他Bean实例化前就处理它) - 调用
setSystemPropertiesMode方法,传入PropertySourcesPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE这个常量,它的值是2,作用就是让系统属性优先,覆盖其他属性源里的同名值
给你贴个代码示例,一看就懂:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @Configuration public class TestIntegrationConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); // 开启系统属性优先模式 configurer.setSystemPropertiesMode(PropertySourcesPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE); return configurer; } }
这样设置之后,当Spring解析${xxx}这类占位符时,会先去系统属性里找对应的值,找到就直接用,找不到再去其他属性源(比如配置文件)里搜,完美实现你要的优先级。
要是你需要更精细的属性源顺序控制(比如还要调整其他属性源的位置),也可以手动操作Environment里的PropertySources,把systemProperties移到最前面,代码大概是这样:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.StandardEnvironment; @Configuration public class TestIntegrationConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); ConfigurableEnvironment environment = new StandardEnvironment(); MutablePropertySources propertySources = environment.getPropertySources(); // 把systemProperties属性源移到第一个位置 String systemPropsName = StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME; if (propertySources.contains(systemPropsName)) { var systemProps = propertySources.remove(systemPropsName); propertySources.addFirst(systemProps); } configurer.setEnvironment(environment); return configurer; } }
不过一般来说,第一种方法就足够解决问题了,简单又高效。
备注:内容来源于stack exchange,提问作者Harold L. Brown
相关产品推荐
相关产品推荐

