SpringCloud源码解析之Config


前言

Config 服务端默认的存储实现是 Git ,这能够很容易地支持配置环境的标签版本,而且有各种工具方便地管理这些配置内容,包括统一配置实时推送,不同环境隔离管理等特点。


一、基础使用

1、server端

1.1、增加pom配置

 <dependencies>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-config-server</artifactId>
     </dependency>
 </dependencies>

1.2、入口类添加@EnableConfigServer 注解

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
 public static void main(String[] args) {
     new SpringApplicationBuilder(ConfigServerApplication.class).web(WebApplicationType.SERVLET).run(args);
 }

1.3、配置信息:

// 服务名称
spring.application.name = config-server-eureka
// 服务的端口号
server.port = 60001
// 与Eureka Server交互的地址,客户端的查询服务和注册服务都需要依赖这个地址
eureka.client.serviceUrl.defaultZone = http://localhost:20000/eureka/
// Git仓库的地址
spring.cloud.config.server.git.uri = 
// Git仓库地址下的相对地址,使用“,”分割
spring.cloud.config.server.git.search-paths = 
// Git仓库的账号
spring.cloud.config.server.git.username = 
// Git仓库的密码
spring.cloud.config.server.git.password = 

2、client端

2.1、增加pom配置:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

2.2、配置文件:

// Git上配置文件的名称
spring.cloud.config.name = config-name
// 获取配置的策略 建议由外部注入
spring.cloud.config.profile = prod
// 获取配置文件的分支,默认是master。如果是是本地获取的话,则无用
spring.cloud.config.label = master
// 开启配置信息发现
spring.cloud.config.discovery.enabled = true
// 配置中心的service-id,便于扩展为高可用配置集群
spring.cloud.config.discovery.serviceId = config-server-eureka
// 与Eureka Server交互的地址,客户端的查询服务和注册服务使用
eureka.client.serviceUrl.defaultZone=http://localhost:8005/eureka/

2.3、入口类代码:

@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
		System.out.println("配置中心客户端启动成功!");
	}
}

二、源码解析

在这里插入图片描述

Config Server加载资源文件

1.1、从启动类的@EnableConfigServer注解进入

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

}

1.2、其中Import了ConfigServerConfiguration

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

1.3、通过Marker了解到,开启了ConfigServerConfiguration类:
当启用了 Config Server之后,配置服务器在启动时就需要对 Config Server 进行自动配置,在 ConfigServerAutoConfiguration类中引入了多个配置类:
EnvironmentRepositoryConfiguration:环境变量存储相关的配置
CompositeConfiguration:组合方式的环境仓储配置
ResourceRepositoryConfiguration:资源仓储相关的配置
ConfigServerEncryptionConfiguration:加密端点的配置
ConfigServerMvcConfiguration:对外暴露的 MVC 端点控制器的配置

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

}

1.4、EnvironmentRepositoryConfiguration类是配置中心的关键Configuration类
EnvironmentRepositoryConfiguration通过profile注解(对当前应用的环境)决定使用装配哪个EnvironmentRepository Bean
EnvironmentRepository是一个配置管理仓库接口,抽象了获取配置的方法
在这里插入图片描述
1.5、进入到重要的EnvironmentController,就是对外提供接口的类
在这里插入图片描述

在这里插入图片描述
1.6、name就是对应的服务名,profiles对应的是环境名,label对应的是分支名

@RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(@PathVariable String name, @PathVariable String profiles,@PathVariable String label) {
	if (name != null && name.contains("(_)")) {
		// "(_)" is uncommon in a git repo name, but "/" cannot be matched
		// by Spring MVC
		name = name.replace("(_)", "/");
	}
	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);
	if (!this.acceptEmpty
			&& (environment == null || environment.getPropertySources().isEmpty())) {
		throw new EnvironmentNotFoundException("Profile Not found");
	}
	return environment;
}

1.7、 进入defaultLabel方法,它会再调用labelled方法,在labelled方法中,会调用repository的findOne()来加载配置,然后返回给配置获取方

@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;
}

在这里插入图片描述
EnvironmentEncryptorEnvironmentRepository类中的findOne()方法:

public class EnvironmentEncryptorEnvironmentRepository implements EnvironmentRepository {

	private EnvironmentRepository delegate;

	private EnvironmentEncryptor environmentEncryptor;

	private Map<String, String> overrides = new LinkedHashMap<>();

	public EnvironmentEncryptorEnvironmentRepository(EnvironmentRepository delegate) {
		this(delegate, null);
	}

	public EnvironmentEncryptorEnvironmentRepository(EnvironmentRepository delegate,
			EnvironmentEncryptor environmentEncryptor) {
		this.delegate = delegate;
		this.environmentEncryptor = environmentEncryptor;
	}

	@Override
	public Environment findOne(String name, String profiles, String label) {
		// 代理模式
		Environment environment = this.delegate.findOne(name, profiles, label);
		if (this.environmentEncryptor != null) {
			environment = this.environmentEncryptor.decrypt(environment);
		}
		if (!this.overrides.isEmpty()) {
			environment.addFirst(new PropertySource("overrides", this.overrides));
		}
		return environment;
	}

	/**
	 * @param overrides the overrides to set
	 */
	public void setOverrides(Map<String, String> overrides) {
		this.overrides = new HashMap<>(overrides);
		for (String key : overrides.keySet()) {
			if (overrides.get(key).contains("\\{")) {
				this.overrides.put(key, overrides.get(key).replace("\\{", "{"));
			}
			if (overrides.get(key).contains("\\${")) {
				this.overrides.put(key, overrides.get(key).replace("\\${", "${"));
			}
		}
	}

}

使用git命令,在本地存了一份文件,直接先删除之前保存的,更新保存新的配置文件
在这里插入图片描述

c对应的git命令在这里插入图片描述
从git上拉取的配置文件在本地的保存地址
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值