【SpringBoot 基礎系列】實現一個自定義配置載入器(應用篇)
阿新 • • 發佈:2020-05-07
![](https://spring.hhui.top/spring-blog/imgs/200507/logo.jpg)
> [【SpringBoot 基礎系列】實現一個自定義配置載入器(應用篇)](https://mp.weixin.qq.com/s?__biz=MzU3MTAzNTMzMQ==&mid=2247484640&idx=1&sn=5ac20b68d7b539295dabc0c2aaf81314)
Spring 中提供了`@Value`註解,用來繫結配置,可以實現從配置檔案中,讀取對應的配置並賦值給成員變數;某些時候,我們的配置可能並不是在配置檔案中,如存在 db/redis/其他檔案/第三方配置服務,本文將手把手教你實現一個自定義的配置載入器,並支援`@Value`的使用姿勢
## I. 環境 & 方案設計
### 1. 環境
- SpringBoot `2.2.1.RELEASE`
- IDEA + JDK8
### 2. 方案設計
自定義的配置載入,有兩個核心的角色
- 配置容器 `MetaValHolder`:與具體的配置打交道並提供配置
- 配置繫結 `@MetaVal`:類似`@Value`註解,用於繫結類屬性與具體的配置,並實現配置初始化與配置變更時的重新整理
上面`@MetaVal`提到了兩點,一個是初始化,一個是配置的重新整理,接下來可以看一下如何支援這兩點
#### a. 初始化
初始化的前提是需要獲取到所有修飾有這個註解的成員,然後藉助`MetaValHolder`來獲取對應的配置,並初始化
為了實現上面這一點,最好的切入點是在 Bean 物件建立之後,獲取 bean 的所有屬性,檢視是否標有這個註解,可以藉助`InstantiationAwareBeanPostProcessorAdapter`來實現
#### b. 重新整理
當配置發生變更時,我們也希望繫結的屬性也會隨之改變,因此我們需要儲存`配置`與`bean屬性`之間的繫結關係
`配置變更` 與 `bean屬性的重新整理` 這兩個操作,我們可以藉助 Spring 的事件機制來解耦,當配置變更時,丟擲一個`MetaChangeEvent`事件,我們預設提供一個事件處理器,用於更新通過`@MetaVal`註解繫結的 bean 屬性
**使用事件除了解耦之外,另一個好處是更加靈活,如支援使用者對配置使用的擴充套件**
## II. 實現
### 1. MetaVal 註解
提供配置與 bean 屬性的繫結關係,我們這裡僅提供一個根據配置名獲取配置的基礎功能,有興趣的小夥伴可以自行擴充套件支援 SPEL
```java
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MetaVal {
/**
* 獲取配置的規則
*
* @return
*/
String value() default "";
/**
* meta value轉換目標物件;目前提供基本資料型別支援
*
* @return
*/
MetaParser parser() default MetaParser.STRING_PARSER;
}
```
請注意上面的實現,除了 value 之外,還有一個 parser,因為我們的配置 value 可能是 String,當然也可能是其他的基本型別如 int,boolean;所以提供了一個基本的型別轉換器
```java
public interface IMe