当前位置:   article > 正文

Spring Cloud Config原理_springcloud config原理

springcloud config原理


最近学习SpringCloud感觉要疯了,硬着头皮写完了原理分析,有些原理理解的不是很透彻,还需要在琢磨琢磨。坚持吧!

1 @Value注解

通过上篇代码可知,我们只需要使用 @Value 注解,就能完成属性的注入。而 @Value 基于 Environment 的机制。我们先来看一下 @Value的注入过程,而 @Value 基于 Environment 的机制,具体请参考spring-cloud-config 源码解析,本文主要讲Environment初始化过程。

2 Spring Environment的初始化

在spring boot的启动流程中,有一个 prepareEnvironment 方法,这个方法就是用来准备Environment这个对象的,

  • springApplication.run -> prepareEnvironment
    这个方法主要就是创建和配置spring容器的环境信息,源码如下
	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
   
		//根据上下文,创建一个合适的Environment对象
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		//配置Environment的propertySource、以及profile
		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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.1 getOrCreateEnvironment

点击getOrCreateEnvironment() ,这个方法是根据当前的webApplication类型匹配对应的environment,当前默认的应该就是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();
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

StandardServletEnvironment 是整个spring boot应用运行环境的实现类,后面所有的关于环境相关的配置操作都是基于这个类,它的类的结构图如下:
在这里插入图片描述
StandardServletEnvironment 的初始化过程
StandardServletEnvironment创建实例时会调用父类AbstractEnvironment无参构造器,AbstractEnvironment ,在这个类的构造方法中,会
调用一个自定义配置文件的方法customizePropertySources(). 这个方法被StandardServletEnvironment重写,所以最终调用StandardServletEnvironment 中的 customizePropertySources 方法

protected void customizePropertySources(MutablePropertySources propertySources) {
   
		propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
		propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
		if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
   
			propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
		}
		super.customizePropertySources(propertySources);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里是将几个不同的配置源封装成 StubPropertySource 和JndiPropertySource添加到
MutablePropertySources 中,调用 addLast 是表示一直往最后的位置添加。
SERVLET_CONFIG_PROPERTY_SOURCE_NAME:servlet的配置信息
SERVLET_CONTEXT_PROPERTY_SOURCE_NAME: 这个是servlet初始化的上下文,也就是以前我们在web.xml中配置的 context-param 。
JNDI_PROPERTY_SOURCE_NAME: 加载jndi.properties配置信息。

MutablePropertySources
在上面的代码中可以看到,所有的外部资源配置都是添加到了一个MutablePropertySources对象中,这个对象封装了属性资源的集合。
在AbstractEnvironment 这个类里定义了MutablePropertySources。并且把这个MutablePropertySources作为参数传递给了ConfigurablePropertyResolver 配置解析器中,而这个配置解析器是一个PropertySourcesPropertyResolver 实例。

public abstract class AbstractEnvironment implements ConfigurableEnvironment {
    
	private final MutablePropertySources propertySources = new MutablePropertySources(); 
	private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources); 
	}
  • 1
  • 2
  • 3
  • 4
  • 5

来看一下这个类关系图
在这里插入图片描述
AbstractEnvironment 实现了文件解析器ConfigurablePropertyResolver ,而在上面这段代码中我们把 MutablePropertySources 传递到PropertySourcesPropertyResolver 中。这样就可以让 AbstractEnvironment 具备文件解析的功能,只是这个功能,委托给了PropertySourcesPropertyResolver来实现

2.2 configureEnvironment()

接下来再看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);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

1 点击configurePropertySources()

protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
   
		MutablePropertySources sources = environment.getPropertySources();
		//设置defaultProperties属性来源,如果设置了默认属性,则会加载
		if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
   
			sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
		}
		//设置commandLineProperties来源,如果设置了命令行参数,则会加载
		if (this.addCommandLineProperties && args.length > 0) {
   
			String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
			if (sources.contains</
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号