Spring中如何加载数量未知的外部配置文件列表?
动态加载外部配置文件并让Environment读取的解决方案
问题背景
我有一个数量未知的待加载配置文件列表,需要通过运行时VM参数获取外部文件路径来加载,没法提前确定文件列表,所以用不了@PropertySources注解。试过用PropertySourcesPlaceholderConfigurer实现,代码如下:
@Bean public static PropertySourcesPlaceholderConfigurer properties() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); List<String> configLocations = loadConfigLocations(); List<Resource> resourceList = new ArrayList<>(); configLocations.forEach(location -> resourceList.add(new FileSystemResource(location))); configurer.setLocations(resourceList.toArray(new Resource[]{})); return configurer; }
但这种方式只能解析@Value("${...}")里的属性,用Environment获取属性时返回null:
@Autowired Environment env; ... String myProp = env.getProperty("my.property")
解决方法
这是因为PropertySourcesPlaceholderConfigurer只负责把属性注入到@Value注解标注的字段,并不会把这些属性纳入Spring的Environment上下文。要让Environment也能读到这些配置,得用EnvironmentPostProcessor来实现动态加载:
- 自定义
EnvironmentPostProcessor实现类,在Spring启动阶段加载外部配置并添加到Environment:
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { // 从VM参数或其他渠道获取配置文件路径列表 List<String> configLocations = loadConfigLocations(); for (String location : configLocations) { Resource resource = new FileSystemResource(location); if (resource.exists()) { try { Properties properties = PropertiesLoaderUtils.loadProperties(resource); // 将加载的属性添加到Environment,可通过addFirst/addLast控制优先级 environment.getPropertySources().addLast(new PropertiesPropertySource("external-config-" + location, properties)); } catch (IOException e) { // 按需处理加载异常,比如打印日志 e.printStackTrace(); } } } } // 实现自己的配置路径加载逻辑,示例从VM参数-Dconfig.locations=path1,path2读取 private List<String> loadConfigLocations() { String locationsStr = System.getProperty("config.locations"); if (locationsStr != null) { return Arrays.asList(locationsStr.split(",")); } return Collections.emptyList(); } }
- 在
resources/META-INF/spring.factories中注册这个处理器,让Spring启动时自动识别:
org.springframework.boot.env.EnvironmentPostProcessor=com.yourpackage.CustomEnvironmentPostProcessor
注意事项
- 配置文件优先级:用
addFirst会让当前配置优先级更高(覆盖后续加载的同名属性),addLast则优先级更低 - 确保配置文件路径正确且文件存在,避免加载失败
- 非Spring Boot项目可改用
ApplicationContextInitializer实现,核心逻辑同样是修改Environment的属性源
内容的提问来源于stack exchange,提问作者eim equipazo
相关产品推荐
相关产品推荐

