diff --git a/spring-boot/002-dynamic-envronment/.gitignore b/spring-boot/002-dynamic-envronment/.gitignore
new file mode 100644
index 00000000..f6127d9a
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/.gitignore
@@ -0,0 +1,4 @@
+.*
+target/*
+*.iml
+!.gitignore
\ No newline at end of file
diff --git a/spring-boot/002-dynamic-envronment/pom.xml b/spring-boot/002-dynamic-envronment/pom.xml
new file mode 100644
index 00000000..a6808867
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+ spring-boot
+ com.git.hui.boot
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ 002-dynamic-envronment
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot/002-dynamic-envronment/readme.md b/spring-boot/002-dynamic-envronment/readme.md
new file mode 100644
index 00000000..7dbfe83e
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/readme.md
@@ -0,0 +1,12 @@
+## 002-dynamic-envronment
+
+### 项目说明
+
+本项目演示了如何使用自定义的配置源,以及配置的动态刷新
+
+- 自定义 `MapPropertySource`来实现自定义的配置源
+- 通过刷新`MapPropertySource`的source,从而实现配置的动态刷新
+- 注意将其注册到`Envrionment`之后,可以配合`@Value`注解来试下自定义配置源的配置绑定(注意这时候不支持刷新,如果需要配置刷新,结合 002-properties-value 这个项目来实现动态刷新支持)
+
+### 博文说明
+
diff --git a/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/Application.java b/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/Application.java
new file mode 100644
index 00000000..08d77ea7
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/Application.java
@@ -0,0 +1,39 @@
+package com.git.hui.boot.dynamic.env;
+
+import com.git.hui.boot.dynamic.env.config.FilePropertiesSource;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author yihui
+ * @date 2021/6/9
+ */
+@EnableScheduling
+@RestController
+@SpringBootApplication
+public class Application {
+ private Environment environment;
+
+ @Bean
+ public FilePropertiesSource filePropertiesSource(ConfigurableEnvironment environment) {
+ this.environment = environment;
+ FilePropertiesSource filePropertiesSource = new FilePropertiesSource();
+ environment.getPropertySources().addLast(filePropertiesSource);
+ return filePropertiesSource;
+ }
+
+ @GetMapping(path = "get")
+ public String getProperty(String key) {
+ return environment.getProperty(key);
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class);
+ }
+}
diff --git a/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/config/FilePropertiesSource.java b/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/config/FilePropertiesSource.java
new file mode 100644
index 00000000..9f8000e7
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/src/main/java/com/git/hui/boot/dynamic/env/config/FilePropertiesSource.java
@@ -0,0 +1,63 @@
+package com.git.hui.boot.dynamic.env.config;
+
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 这里以从自定义的配置文件中读取配置,来演示配置的数据源自定义(如果希望从redis/db/http获取配置,只需要修改下面的refreshSource;或者修改 getProperty)
+ *
+ * @author yihui
+ * @date 2021/6/9
+ */
+public class FilePropertiesSource extends MapPropertySource {
+ public FilePropertiesSource(String name, Map source) {
+ super(name, source);
+ }
+
+ public FilePropertiesSource() {
+ this("filePropertiesSource", new HashMap<>());
+ }
+
+ // 这种方式,适用于一次捞取所有的配置,然后从内存中查询对应的配置,提高服务性能
+ // 10s 更新一次
+ @PostConstruct
+ @Scheduled(fixedRate = 10_000)
+ public void refreshSource() throws IOException {
+ String ans =
+ FileCopyUtils.copyToString(new InputStreamReader(FilePropertiesSource.class.getClassLoader().getResourceAsStream("kv.properties")));
+ Map map = new HashMap<>();
+ for (String sub : StringUtils.split(ans, "\n")) {
+ if (sub.isEmpty()) {
+ continue;
+ }
+ String[] kv = StringUtils.split(sub, "=");
+ if (kv.length != 2) {
+ continue;
+ }
+
+ map.put(kv[0].trim(), kv[1].trim());
+ }
+
+ source.clear();
+ source.putAll(map);
+ }
+
+ /**
+ * 覆盖这个方法,适用于实时获取配置
+ *
+ * @param name
+ * @return
+ */
+ @Override
+ public Object getProperty(String name) {
+ return super.getProperty(name);
+ }
+}
diff --git a/spring-boot/002-dynamic-envronment/src/main/resources/kv.properties b/spring-boot/002-dynamic-envronment/src/main/resources/kv.properties
new file mode 100644
index 00000000..ea2f27a2
--- /dev/null
+++ b/spring-boot/002-dynamic-envronment/src/main/resources/kv.properties
@@ -0,0 +1,3 @@
+user=xhh
+name=一灰灰
+age=18
\ No newline at end of file
diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml
index c053b7f5..0d3aa62b 100644
--- a/spring-boot/pom.xml
+++ b/spring-boot/pom.xml
@@ -110,6 +110,7 @@
420-prometheus-basic
150-i18n
002-properties-value
+ 002-dynamic-envronment