基于springboot2.1.8。
废话少说我们上代码:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
//创建并配置环境 下面有代码跟踪
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境 下面有代码跟踪
configureEnvironment(environment, applicationArguments.getSourceArgs());
//
ConfigurationPropertySources.attach(environment);
//激活环境准备完毕事件 遍历所有实现了SpringApplicationRunListener接口的类。其中就有EventPublishingRunListener ,而EventPublishingRunListener其实会发出事件,调用监听了本事件的ApplicationListener接口的类。
//这里会激活几个实现ApplicationListener接口的类 比如:ConfigFileApplicationListener SpringApplicationJsonEnvironmentPostProcessor 等
//其中ConfigFileApplicationListener就是添加名叫random的RandomValuePropertySource到名叫systemEnvironment的PropertySource后;并初始化Profiles;初始化PropertiesPropertySourceLoader和YamlPropertySourceLoader这两个加载器从file:./config/,file:./,classpath:/config/,classpath:/路径下加载配置文件,PropertiesPropertySourceLoader加载配置文件application.xml和application.properties,YamlPropertySourceLoader加载配置文件application.yml和application.yaml。目前我们之后classpath:/路径下有个application.yml配置文件,将其属性配置封装进了一个名叫applicationConfig:[classpath:/application.yml]的OriginTrackedMapPropertySource中,并将此对象放到了propertySourceList的最后
//我们画一下方法执行流程ConfigFileApplicationListener的 onApplicationEvent方法会被事件调用,onApplicationEvent方法中 主要有两个方法:onApplicationEnvironmentPreparedEvent和onApplicationPreparedEvent。 onApplicationEnvironmentPreparedEvent -> postProcessor.postProcessEnvironment ->addPropertySources -> new Loader(environment, resourceLoader).load()
//onApplicationEvent方法->addPostProcessors ->context.addBeanFactoryPostProcessor(new PropertySourceOrderingPostProcessor(context)); 这块就是想环境中加入了BeanFactoryPostProcessor。后期上下文刷新refresh()方法里面会调用到。
listeners.environmentPrepared(environment);
//生成一个binder 把环境 转换器 等绑定到一起
bindToSpringApplication(environment);
// 验证环境 是web环境强制转成StandardEnvironment 否则使用转换器转
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
//
ConfigurationPropertySources.attach(environment);
return environment;
}
我们先看getOrCreateEnvironment方法,根据前面的web类型返回对应的环境对象,web类型通常为SERVLET所以返回new StandardServletEnvironment()。
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
//加载环境
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
然后我们接着看configureEnvironment方法。上代码:
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
//获得一个数据转换器conversionService
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
//把转换器set到环境中
environment.setConversionService((ConfigurableConversionService) conversionService);
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
继续分析下一个方法:
public static void attach(Environment environment) {
// 判断environment是否是ConfigurableEnvironment的实例
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
//获取PropertySources
MutablePropertySources sources = ((ConfigurableEnvironment) environment)
.getPropertySources();
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
if (attached != null && attached.getSource() != sources) {
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
attached = null;
}
if (attached == null) {
// 将sources封装成ConfigurationPropertySourcesPropertySource对象,并把这个对象放到sources的第一位置
sources.addFirst(new ConfigurationPropertySourcesPropertySource(
ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources)));
}
}