SpringCloud学习笔记(二)-Config配置

358 阅读2分钟

Config分为三个部分:ConfigServer ConfigClient 配置仓库

一、ConfigServer如何提供配置

SpringCloud中申明ConfigServer时,通过@EnableConfigServer开启ConfigServer配置。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigServerConfiguration.class)
public @interface EnableConfigServer {

}

而EnableConfigServer中又引入了ConfigServerConfiguration,申明了内部类Maker,并装配为一个Bean。

@Configuration
public class ConfigServerConfiguration {
	class Marker {}

	@Bean
	public Marker enableConfigServerMarker() {
		return new Marker();
	}
}

通过ConfigServerConfiguration.Maker又开启了ConfigServerAutoConfiguration配置(通过@ConditionalOnBean(ConfigServerConfiguration.Marker.class)开启,在装配Maker时会执行该配置)。

@Configuration
@ConditionalOnBean(ConfigServerConfiguration.Marker.class)
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,
		ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class, TransportConfiguration.class })
public class ConfigServerAutoConfiguration {

}

通过@Import引入了6个重要的配置类 EnvironmentRepositoryConfiguration:环境仓库配置,是关键的配置类 CompositeConfiguration:混合配置,用于多环境下配置资源的加载 ResourceRepositoryConfiguration:资源仓库相关配置 ConfigServerEncryptionConfiguration:ConfigServer加密相关配置 ConfigServerMvcConfiguration:对外暴露的MVC相关配置 TransportConfiguration:运行transport命令前,配置回调

EnvironmentRepositoryConfiguration的配置

环境仓库的配置又细分为JDBCVaultsvnNative(本地)Git等配置,默认是Git配置. 多种配置方式,最终都会被装配成EnvironmentRepository,以本地配置装配为例看下类图结构:

EnvironmentRepository

1. NativeEnvironmentRepository本地配置加载
2. GitRepositoryConfiguration Git配置加载

等等...

二、ConfigClient的调用

ConfigServer在启动的时候会申明一个REST接口(EnvironmentController)当有配置客户端查询请求时,通过调用EnvironmentRepository.findOne方法返回一个Environment对象,客户端反序列化得到Environment对象。

@RequestMapping("/{name}/{profiles:.*[^-].*}")
	public Environment defaultLabel(@PathVariable String name,
			@PathVariable String profiles) {
		return labelled(name, profiles, null);
}
@RequestMapping("/{name}/{profiles}/{label:.*}")
	public Environment labelled(@PathVariable String name, @PathVariable String profiles,
			@PathVariable String label) {
		if (label != null && label.contains("(_)")) {
			// "(_)" is uncommon in a git branch name, but "/" cannot be matched
			// by Spring MVC
			label = label.replace("(_)", "/");
		}
		Environment environment = this.repository.findOne(name, profiles, label);
		return environment;
}

findOne根据配置信息解析过滤配置属性,封装为Environment对象返回给客户端。

public class NativeEnvironmentRepository{
//在ConfigClient启动时调用
//config:文件名称,即在Configclient中配置的config.name
//profile:ConfigClient中配置的config.profile
@Override
public Environment findOne(String config, String profile, String label) {
        //启动一个SpringBoot内部微型工程,用于加载配置文件
		SpringApplicationBuilder builder = new SpringApplicationBuilder(
				PropertyPlaceholderAutoConfiguration.class);
		ConfigurableEnvironment environment = getEnvironment(profile);
		builder.environment(environment);
		builder.web(false).bannerMode(Mode.OFF);
		if (!logger.isDebugEnabled()) {
			// Make the mini-application startup less verbose
			builder.logStartupInfo(false);
		}
		String[] args = getArgs(config, profile, label);
		// Explicitly set the listeners (to exclude logging listener which would change
		// log levels in the caller)
		builder.application()
				.setListeners(Arrays.asList(new ConfigFileApplicationListener()));
		ConfigurableApplicationContext context = builder.run(args);
		environment.getPropertySources().remove("profiles");
		try {
            //过滤出所有配置
			return clean(new PassthruEnvironmentRepository(environment).findOne(config,
					profile, label));
		}
		finally {
			context.close();
		}
	}
}

返回的Environment对象也可以直接通过在地址栏输入http连接看到

Environment