获取属性源码跟踪解析
入口方法
@Component
public class EnvironmentDebugger implements CommandLineRunner, EnvironmentAware {
private Environment environment;
@Override
public void run(String... args) throws Exception {
String study2 = environment.getProperty("study2");
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
实现EnvironmentAware 接口,获取Environment对象
实现CommandLineRunner接口,在容器启动完成后,获取key的值,作为源码跟踪的入口
源码跟踪
根据入口environment.getProperty,一直点进入org.springframework.core.env.PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class, boolean),可以看到最基础的实现
@Nullable
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
for (PropertySource<?> propertySource : this.propertySources) {
if (logger.isTraceEnabled()) {
logger.trace("Searching for key '" + key + "' in PropertySource '" +
propertySource.getName() + "'");
}
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Could not find key '" + key + "' in any property source");
}
return null;
}
方法中可以看出通过key获取属性值,遍历propertySources中存放的PropertySource,并且从中依次取出属性,如果所有都没有取到,则返回NULL
可以看出propertySources中共存在7中类型的属性,可以找到我们设置的默认属性,并且已键值对存放数据
PropertySource源码
public abstract class PropertySource<T> {
protected final Log logger = LogFactory.getLog(getClass());
protected final String name;
protected final T source;
}
source为存放属性的具体实现
通过获取属性可以看出所有的属性都存放在:propertySources中,只需要搞懂spring容器在启动的时候是如何装载自定义的属性进propertySources就可以
Environment加载属性
入口函数
springApplication.run(args) --> prepareEnvironment
prepareEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
configureAdditionalProfiles(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
在prepareEnvironment中,共进行了一下的进步操作:
- 创建Environment对象:getOrCreateEnvironment()
- 配置属性:configureEnvironment()
- 添加configurationProperties属性:ConfigurationPropertySources.attach(environment)
- 通过事件发布器发布environment事件:listeners.environmentPrepared(bootstrapContext, environment);
- 将defaultProperties属性移到最后面,因为是默认,所有在后面兜底:DefaultPropertiesPropertySource.moveToEnd(environment)
- 加载profile配置文件属性:configureAdditionalProfiles(environ