1. 问题说明
将Springboot项目中自定义的一个扩展工具类移植到Spring框架项目中的时候发现一个问题。在springboot中application.yml中的配置内容可以从Environment中获取,但是在spring中context:placeholder对应的配置文件中的配置却无法从Environment中获取。为了搞清楚这一问题,对该部分源码进行深入阅读。
2. Spring中placeholder
2.1 核心源码
2.2 代码示例
import org.junit.jupiter.api.Test;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import java.util.Properties;
/**
* @author pp_lan
*/
public class PropertiesPropertySourceDemo {
@Test
public void test01() {
Properties properties = new Properties();
properties.put("dbType", "postgresql");
PropertiesPropertySource simplePropertySource = new PropertiesPropertySource("simple", properties);
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(simplePropertySource);
PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
String dbType = resolver.resolvePlaceholders("${dbType}");
System.out.println(dbType);
}
}
DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'dbType' in PropertySource 'simple' with value of type String
postgresql
Process finished with exit code 0
3. Springboot中application.yml
3.1 流程图
3.2 源码解析
3.2.1 EnvironmentPostProcessorApplicationListener
3.2.2 加载所有的postProcessor,包括自定义的扩展类
类名 | 作用 |
SystemEnvironmentPropertySourceEnvironmentPostProcessor | 加载环境变量 |
ConfigDataEnvironmentPostProcessor | 读取配置处理类 |
3.2.3 读取配置回填入口
org.springframework.boot.context.config.ConfigDataEnvironment
3.2.4 配置读取
org.springframework.boot.context.config.ConfigDataEnvironmentContributor
org.springframework.boot.context.config.StandardConfigDataLoader
StandardConfigDataLoader.load根据resouce的类型选择对应的策略sourceLoader(例如:yml文件选择YamlPropertySourceLoader)
org.springframework.boot.env.YamlPropertySourceLoader
4. 总结
二者主要区别如下:
- placeholder的方式为变量替换
- application.yml的读取是将配置内容放入到environment中
因此,导致了Spring无法从Environment中读取的问题。