SpringBoot源码阅读(8)——系统环境创建

07-11 859阅读

SpringBoot创建系统应用上下文是在run方法,第301行。

ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
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);
	Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
			"Environment prefix cannot be set via properties.");
	bindToSpringApplication(environment);
	if (!this.isCustomEnvironment) {
		EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
		environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
	}
	ConfigurationPropertySources.attach(environment);
	return environment;
}
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
private ConfigurableEnvironment getOrCreateEnvironment() {
	if (this.environment != null) {
		return this.environment;
	}
	ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
	if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
		environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
	}
	return (environment != null) ? environment : new ApplicationEnvironment();
}
ApplicationContextFactory DEFAULT = new DefaultApplicationContextFactory();

最后具体的加载逻辑在

@Override
	public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
		return getFromSpringFactories(webApplicationType, ApplicationContextFactory::createEnvironment, null);
	}

仍然是一个工厂类:ApplicationContextFactory

这个工厂类有两个实现。

# Application Context Factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory

算上默认的ApplicationEnvironment,有三个上下文环境类型,刚好对应了WebApplicationType的三个枚举值。

AnnotationConfigReactiveWebServerApplicationContext.Factory

注释:

接受带注释类作为输入的ReactiveWebServerApplicationContext,特别是@Configuration带注释类,还接受使用javax.inject注释的普通@Component类和JSR-330兼容类。允许一个接一个地注册类(将类名指定为配置位置)以及类路径扫描(将基本包指定为配置地点)。

注意:如果有多个@Configuration类,稍后的@Bean定义将覆盖先前加载的文件中定义的定义。这可以用来通过一个额外的Configuration类故意覆盖某些bean定义。

SpringBoot源码阅读(8)——系统环境创建

如果是REACTIVE类型,就创建一个ApplicationReactiveWebEnvironment类。

AnnotationConfigServletWebServerApplicationContext.Factory

注释:

ServletWebServerApplicationContext,它接受带注释的类作为输入,特别是@Configuration注释的类,也接受普通的@Component类和使用javax.inject注释的JSR-330兼容类。允许一个接一个地注册类(将类名指定为配置位置)以及类路径扫描(将基本包指定为配置地点)

注意:如果有多个@Configuration类,稍后的@Bean定义将覆盖先前加载的文件中定义的定义。这可以用来通过一个额外的Configuration类故意覆盖某些bean定义。

SpringBoot源码阅读(8)——系统环境创建

如果应用类型是SERVLET,就创建一个ApplicationServletEnvironment类。

java中实例化一个类,会同时调用父类的构造方法。

SpringBoot源码阅读(8)——系统环境创建

ApplicationServletEnvironment

继承关系:StandardServletEnvironment、StandardEnvironment、AbstractEnvironment

在AbstractEnvironment抽象类中,创建了一个类。

public AbstractEnvironment() {
	this(new MutablePropertySources());
}
protected AbstractEnvironment(MutablePropertySources propertySources) {
	this.propertySources = propertySources;
	this.propertyResolver = createPropertyResolver(propertySources);
	customizePropertySources(propertySources);
}

最终,propertySources是一个MutablePropertySources 类型。

propertyResolver则是被使用子类createPropertyResolver方法返回的值。

@Override
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
	return ConfigurationPropertySources.createPropertyResolver(propertySources);
}

创建了一个ConfigurationPropertySourcesPropertyResolver类,再创建一个DefaultResolver,持有propertySources。

然后调用子类customizePropertySources方法。

public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams";
public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";
private static final boolean jndiPresent = ClassUtils.isPresent(
			"javax.naming.InitialContext", StandardServletEnvironment.class.getClassLoader());
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
	propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
	propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
	if (jndiPresent && JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
		propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
	}
	super.customizePropertySources(propertySources);
}

把servlet上下文参数和servlet配置参数放入propertySources,占位。

然后调用父类方法

public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
	propertySources.addLast(
			new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
	propertySources.addLast(
			new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

把系统环境变量和JVM环境变量添加到propertySources中。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]