配置動態刷新@RefreshScope引起的取值爲null

配置動態刷新@RefreshScope引起的取值爲null

 在Spring Cloud Config 動態刷新demo編寫中,分爲三個步驟:

 1)git端配置更改,代碼提交

 2)手動刷新配置: POST請求: http://localhost:3355/actuator/refresh

 

 3)客戶端訪問配置:http://localhost:3355/testConfig

 控制類代碼如下:

 1 @RestController
 2 @RefreshScope
 3 public class ConfigClientTestController {
 4     @Value("${config.info}")
 5     private String configInfo;
 6     
 7     /**
 8      * 讀取配置文件內容
 9      *
10      * @return
11      */
12     @GetMapping("testConfig")
13     private String configInfo() {
14         return configInfo;
15     }
16 }

  這個時候發現問題,客戶端根本讀取不到配置。

  分析:

   1)@RefreshScope 註解是 Spring Cloud 中用於標記需要在配置發生變化時進行刷新的 bean 的註解。當一個 bean 被 @RefreshScope 註解標記時,Spring 在創建這個 bean 的代理對象時會注入一些額外的邏輯,以便在配置變化時刷新這個 bean 的屬性值。

   2)代理對象是 Spring Framework 在運行時動態創建的對象,它包裝了真實的 bean 對象,並在需要時執行一些額外的操作,比如在配置變化時刷新屬性值。在使用 @RefreshScope 註解時,Spring 創建了一個代理對象來管理被註解標記的 bean,並在需要時負責刷新這個 bean 的屬性值。

   3)當我們在調用方法時,實際上是調用了代理對象的方法,代理對象會負責處理實際的調用邏輯,包括在配置變化時刷新屬性值。因此,通過方法調用可以獲取到最新的屬性值,但直接訪問 bean 的字段可能會得到舊值或者 null,因爲直接訪問的是代理對象的字段,而不是真實的 bean 對象。

   根據上面的分析,將代碼再改動一下:

 1 @RestController
 2 @RefreshScope
 3 public class ConfigClientTestController {
 4     @Value("${config.info}")
 5     private String configInfo;
 6 
 7     public String getConfig() {
 8         return configInfo;
 9     }
10 
11     /**
12      * 讀取配置文件內容
13      *
14      * @return
15      */
16     @GetMapping("testConfig")
17     private String configInfo() {
18         return getConfig();
19     }
20 }

    這樣就可以正常讀取值了。

    @RefreshScope 會使注入的值放到代理類中,而當前bean的屬性字段是沒有值的,直接讀取bean的field會爲null,只有通過方法(不一定是get方法)纔會觸發去代理類中取值

   看到網上很多文章提到在@Controller中直接@Value獲取不到值,解決方法是定義另外一個配置類,再取值就可以了。

   配置類:

 1 @Component
 2 @RefreshScope
 3 public class ConfigData {
 4     @Value("${config.info}")
 5     private String configInfo;
 6 
 7     public String getConfigInfo() {
 8         return configInfo;
 9     }
10 }

   控制類:

 1 @RestController
 2 @RequiredArgsConstructor(onConstructor_ = {@Autowired})
 3 public class ConfigClientController {
 4 
 5     private final ConfigData configData;
 6 
 7     /**
 8      * 讀取配置文件內容
 9      *
10      * @return
11      */
12     @GetMapping("getConfigInfo")
13     private String configInfo() {
14         return configData.getConfigInfo();
15     }
16 }

  這樣也能正常讀取到手動刷新後的配置值。不過,歸根結底,出現讀取不到最新值的原因其實跟取值方式有關, 都是代理惹的禍。

取值方式  無@RefreshScope 有@RefreshScope
方式1(field取值)  有值  null
方式2(方法取值)  有值  有值

 

 

 

 

 

 

 參考鏈接: https://www.jianshu.com/p/a535f8250cb2 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章