Environment环境加载
Environment就是指Spring应用运行的环境信息,例如从系统变量、命令行、配置文件application.yml等文件中的信息加载之后都会保存到Environment中。
Environment的初始化
org.springframework.boot.SpringApplication#run(java.lang.String...)
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
准备环境的过程中,主要就是创建和配置Spring容器的环境信息:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
//按照应用的类型创建标准的环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境的PropertySource,设置profiles
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
//事件驱动加载环境配置
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
1. 创建一个标准的环境
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
//若是Servlet应用则创建Servlet环境
return new StandardServletEnvironment();
case REACTIVE:
//若是reactive应用则创建Servlet环境
return new StandardReactiveWebEnvironment();
default:
//否则创建标准环境
return new StandardEnvironment();
}
}
获取webApplicationType: org.springframework.boot.WebApplicationType#deduceFromClasspath
static WebApplicationType deduceFromClasspath() {
//org.springframework.web.reactive.DispatcherHandler类存在,
//且org.springframework.web.servlet.DispatcherServlet类不存在
//且org.glassfish.jersey.servlet.ServletContainer类不存在,则为REACTIVE应用
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
//javax.servlet.Servlet类
//或org.springframework.web.context.ConfigurableWebApplicationContext类不存在则为普通的应用
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
//否则为Servlet应用
return WebApplicationType.SERVLET;
}
这里以Servlet应用为例,看下环境的类结构图:
StandardServletEnvironment初始化
由于AbstractEnvironment类初始化调用了customizePropertySource方法,而customizePropertySource在StandardServletEnvironment和StandardEnvironment都有重写,所以会优先执行他们的方法:
org.springframework.web.context.support.StandardServletEnvironment#customizePropertySources
protected void customizePropertySources(MutablePropertySources propertySources) {
//将Servlet的配置封装成一个标准的属性源添加到动态可变的属性源列表中
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
//将Servlet的上下文封装成一个标准的属性源添加到动态可变的属性源列表中
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
//添加JNDI的属性源
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
super.customizePropertySources(propertySources);
}
org.springframework.core.env.StandardEnvironment#customizePropertySources
protected void customizePropertySources(MutablePropertySources propertySources) {
将系统属性源System.getProperties()添加到动态可变的属性源列表中
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
//将系统环境属性System.getenv()添加到动态可变的属性源列表中
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
2.配置Environment和配置profiles
org.springframework.boot.SpringApplication#configureEnvironment
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
//添加类型转化的服务
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
//配置Environment中的propertysources
configurePropertySources(environment, args);
//配置profiles
configureProfiles(environment, args);
}
org.springframework.boot.SpringApplication#configurePropertySources
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
MutablePropertySources sources = environment.getPropertySources();
//若默认配置不为空,则将默认配置添加到MutablePropertySources,这个defaultProperties可以在SpringApplication中设置
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(new MapPr