Spring Cloud Config Client原理讲解

Posted dszazhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Config Client原理讲解相关的知识,希望对你有一定的参考价值。

# Spring Cloud Config Client

 

## 预备知识

 

### 发布/订阅模式

`java.util.Observable` 是一个发布者

`java.util.Observer` 是订阅者

 

发布者和订阅者:1 : N

发布者和订阅者:N : M

 

### 事件/监听模式

`java.util.EventObject` :事件对象

? * 事件对象总是关联着事件源(source)

`java.util.EventListener` :事件监听接口(标记)

 

## Spring 事件/监听

`ApplicationEvent` : 应用事件

`ApplicationListener` : 应用监听器

 

### Spring Boot 事件/监听器

 

#### ConfigFileApplicationListener

管理配置文件,比如:`application.properties` 以及 `application.yaml`

`application-{profile}.properties`:

profile = dev 、test

1. `application-{profile}.properties`
2. application.properties

 

Spring Boot 在相对于 ClassPath : /META-INF/spring.factories

 

Java SPI : `java.util.ServiceLoader`

Spring SPI:

Spring Boot "/META-INF/spring.factories"

```properties
org.springframework.context.ApplicationListener=
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,
org.springframework.boot.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.logging.LoggingApplicationListener
```

##### 如何控制顺序

实现`Ordered` 以及 标记`@Order`

在 Spring 里面,数值越小,越优先

 

### Spring Cloud 事件/监听器

#### BootstrapApplicationListener

 

Spring Cloud "/META-INF/spring.factories":

```properties
# Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.cloud.bootstrap.BootstrapApplicationListener,
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,
org.springframework.cloud.context.restart.RestartListener
```

 

> 加载的优先级 高于 `ConfigFileApplicationListener`,所以 application.properties 文件即使定义也配置不到!
>
> 原因在于:
>
> `BootstrapApplicationListener ` 第6优先
>
> `ConfigFileApplicationListener` 第11优先

1. 负责加载`bootstrap.properties` 或者 `bootstrap.yaml`
2. 负责初始化 Bootstrap ApplicationContext ID = "bootstrap"

```java
ConfigurableApplicationContext context = builder.run();
```

Bootstrap 是一个根 Spring 上下文,parent = null

> 联想 ClassLoader:
>
> ExtClassLoader <- AppClassLoader <- System ClassLoader -> Bootstrap Classloader(null)

 

#### ConfigurableApplicationContext

标准实现类:`AnnotationConfigApplicationContext`

 

### Env 端点:`EnvironmentEndpoint`

 

`Environment` 关联多个带名称的`PropertySource`

可以参考一下Spring Framework 源码:

`AbstractRefreshableWebApplicationContext`

```java
protected void initPropertySources() {
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig);
}
}
```

 

`Environment` 有两种实现方式:

普通类型:`StandardEnvironment`

Web类型:`StandardServletEnvironment`

 

`Environment`

- `AbstractEnvironment`

? - `StandardEnvironment`

 

Enviroment 关联着一个`PropertySources` 实例

`PropertySources` 关联着多个`PropertySource`,并且有优先级

其中比较常用的`PropertySource` 实现:

Java System#getProperties 实现: 名称"systemProperties",对应的内容 `System.getProperties()`

Java System#getenv 实现(环境变量): 名称"systemEnvironment",对应的内容 `System.getProperties()`

 

关于 Spring Boot 优先级顺序,可以参考:https://docs.spring.io/spring-boot/docs/2.0.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-external-config

 

#### 实现自定义配置

1. 实现`PropertySourceLocator`

2. 暴露该实现作为一个Spring Bean

3. 实现`PropertySource`:

```java
public static class MyPropertySourceLocator implements PropertySourceLocator {

@Override
public PropertySource<?> locate(Environment environment) {
Map<String, Object> source = new HashMap<>();
source.put("server.port","9090");
MapPropertySource propertySource =
new MapPropertySource("my-property-source", source);
return propertySource;
}
}
```

4. 定义并且配置 /META-INF/spring.factories:

```properties
org.springframework.cloud.bootstrap.BootstrapConfiguration=
com.gupao.springcloudconfigclient.SpringCloudConfigClientApplication.MyPropertySourceLocator
```

 

注意事项:

`Environment` 允许出现同名的配置,不过优先级高的胜出

内部实现:`MutablePropertySources` 关联代码:

```java
List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();
```

propertySourceList FIFO,它有顺序

可以通过 MutablePropertySources#addFirst 提高到最优先,相当于调用:

`List#add(0,PropertySource);`

 

以上是关于Spring Cloud Config Client原理讲解的主要内容,如果未能解决你的问题,请参考以下文章

无法通过 spring.cloud.config.enabled:false 禁用 Spring Cloud Config

0701-spring cloud config-简介Config Server开发Config Client开发

问题 spring-cloud-config 和 spring-cloud-bus

spring-cloud-config——Quick Start

spring cloud config 8888端口可以变么

spring-cloud-config-server——Environment Repository