欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring應(yīng)用中使用acutator/refresh刷新屬性不生效的問題分析及解決

 更新時間:2024年01月10日 11:43:28   作者:龍鶴鹿  
在Spring應(yīng)用收到/actuator/refresh的POST請求后,標(biāo)注了@RefreshScope以及@ConfiguratioinProperties的bean會被Spring容器重新加載,但是,在實際應(yīng)用中,并沒有按照預(yù)期被Spring容器加載,本文將討論導(dǎo)致這種未按預(yù)期刷新的一種原因,感興趣的朋友可以參考下

問題的引入

在Spring應(yīng)用收到/actuator/refresh的POST請求后,標(biāo)注了@RefreshScope以及@ConfiguratioinProperties的bean會被Spring容器重新加載。這樣,如果配置文件(一般來自于配置中心,或者k8s的ConfigMap)發(fā)生了變化,那么這些變化就會因為Bean的重新加載而被應(yīng)用感知。

但是,在實際應(yīng)用中,可能會發(fā)現(xiàn)有些標(biāo)注了@ConfigurationProperties的bean,并沒有按照預(yù)期被Spring容器加載。本文將討論導(dǎo)致這種未按預(yù)期刷新的一種原因。

結(jié)論

在進(jìn)行詳細(xì)的討論之前,先把結(jié)論寫出來。如果大家時間緊張,而且碰巧遇到了這樣的問題,可以直接根據(jù)結(jié)論把問題解決掉。

確保標(biāo)注了@ConfigurationProperties注解的bean沒有被任何Advisor依賴

比如:如下的Bean就不會被Spring容器刷新。

@ConfigurationProperties(prefix="com.dadaer.test")
public class MyProp {
  //...
}

// ............

@Component
public class MyAdvisor extends AbstractPointcutAdvisor {
   
   private final MyProp myProp;
   
   public class MyAdvisor(MyProp myProp) {
     this.myProp = myProp;
   }

  //...
}

這里的MyAdvisor依賴了MyProp,所以在收到/actuator/refresh的請求以后,MyProp的bean不會被重新加載。

分析

應(yīng)用啟動階段

在Spring應(yīng)用啟動時,在執(zhí)行到AbstractApplicationContext#refresh方法初始化容器的時候,其中有一個步驟(12大步中的第5步),Spring會向容器中注入所有的BeanPostProcessor,代碼如下:

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

而其中有一個BeanPostProcessor叫做:ConfigurationPropertiesBeans,是一個用來注冊所有標(biāo)注了@ConfigurationProperties注解的后置處理器。

在初始化BeanPostProcessor的時候,會經(jīng)歷到下面的一段代碼:

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // TODO: Consider optimization by caching the list of the aspect names
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
       if (advisor instanceof AspectJPointcutAdvisor pointcutAdvisor &&
             pointcutAdvisor.getAspectName().equals(beanName)) {
          return true;
       }
    }
    return super.shouldSkip(beanClass, beanName);
}

這里,會查找所有的Advisor并初始化。這樣,如果某個Advisor(比如上述MyAdvisor)依賴了一個@ConfigurationProperties注解的類(比如上述MyProp)。那么此時MyProp就需要在BeanPostProcessor之前初始化完成,即:MyProp先于ConfigurationPropertiesBeans完成初始化。

應(yīng)用運行階段

在應(yīng)用運行階段,當(dāng)收到/actuator/refresh的POST請求時,會觸發(fā)RefreshEndpoint

@Endpoint(id = "refresh")
public class RefreshEndpoint {
    //...
    @WriteOperation
    public Collection<String> refresh() {
       Set<String> keys = this.contextRefresher.refresh();
       return keys;
    }
}

然后調(diào)用ContextRefresher#refresh方法進(jìn)入下面的代碼:

public synchronized Set<String> refreshEnvironment() {
    Map<String, Object> before = extract(this.context.getEnvironment().getPropertySources());
    updateEnvironment();
    Set<String> keys = changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();
    this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
    return keys;
}

這里,發(fā)送了一個EnvironmentChangeEvent事件,這個事件會被ConfigurationPropertiesRebinder捕獲,如下:

@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
    if (this.applicationContext.equals(event.getSource())
          // Backwards compatible
          || event.getKeys().equals(event.getSource())) {
       rebind();
    }
}

然后rebind方法被調(diào)用:

@ManagedOperation
public void rebind() {
    this.errors.clear();
    for (String name : this.beans.getBeanNames()) {
       rebind(name);
    }
}

這里beans變量的類型是:ConfigurationPropertiesBeans,它里面保存了所有待刷新的ConfigurationProperties的bean。

結(jié)論

因為啟動階段中,MyProp優(yōu)先于ConfigurationPropertiesBeans被加載,導(dǎo)致ConfigurationPropertiesBeans里面不會包含MyProp這個bean,從而導(dǎo)致它不會被刷新。

以上就是Spring應(yīng)用中使用acutator/refresh刷新屬性不生效的問題分析及解決的詳細(xì)內(nèi)容,更多關(guān)于Spring使用acutator/refresh不生效的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot如何進(jìn)行業(yè)務(wù)校驗實例詳解

    SpringBoot如何進(jìn)行業(yè)務(wù)校驗實例詳解

    這篇文章主要給大家介紹了關(guān)于SpringBoot如何進(jìn)行業(yè)務(wù)校驗的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-01-01
  • Mybatis常用標(biāo)簽整理

    Mybatis常用標(biāo)簽整理

    日常開發(fā)中,MyBatis中標(biāo)簽有著舉足輕重的重要性,以下是一些MyBatis框架中常見的標(biāo)簽及案例,感興趣的朋友跟隨小編一起看看吧
    2007-02-02
  • java實用小技巧之判斷l(xiāng)ist是否有重復(fù)項簡單例子

    java實用小技巧之判斷l(xiāng)ist是否有重復(fù)項簡單例子

    這篇文章主要給大家介紹了關(guān)于java實用小技巧之判斷l(xiāng)ist是否有重復(fù)項的相關(guān)資料,在開發(fā)工作中我們有時需要去判斷List集合中是否含有重復(fù)的元素,需要的朋友可以參考下
    2023-10-10
  • springboot集成Mybatis的詳細(xì)教程

    springboot集成Mybatis的詳細(xì)教程

    今天給大家?guī)淼倪€是關(guān)于springboot的相關(guān)知識,文章圍繞著springboot集成Mybatis的詳細(xì)教程展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 使用MQ消息隊列的優(yōu)缺點詳解

    使用MQ消息隊列的優(yōu)缺點詳解

    這篇文章主要介紹了使用MQ消息隊列的優(yōu)缺點詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • java智能問答圖靈機器人AI接口(聚合數(shù)據(jù))

    java智能問答圖靈機器人AI接口(聚合數(shù)據(jù))

    這篇文章主要介紹了java智能問答圖靈機器人AI接口(聚合數(shù)據(jù)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 關(guān)于Java中@SuppressWarnings的正確使用方法

    關(guān)于Java中@SuppressWarnings的正確使用方法

    這篇文章主要介紹了關(guān)于Java中@SuppressWarnings的正確使用方法,@SuppressWarnings注解主要用在取消一些編譯器產(chǎn)生的警告對代碼左側(cè)行列的遮擋,有時候這會擋住我們斷點調(diào)試時打的斷點,需要的朋友可以參考下
    2023-05-05
  • Java Lambda 表達(dá)式詳解及示例代碼

    Java Lambda 表達(dá)式詳解及示例代碼

    本文主要介紹Java Lambda 表達(dá)式的知識,這里整理了相關(guān)資料,JavaLambda 是Java8 引入的新功能,有興趣的小伙伴可以參考下
    2016-09-09
  • 使用?Spring?AI?+?Ollama?構(gòu)建生成式?AI?應(yīng)用的方法

    使用?Spring?AI?+?Ollama?構(gòu)建生成式?AI?應(yīng)用的方法

    通過集成SpringBoot和Ollama,本文詳細(xì)介紹了如何構(gòu)建生成式AI應(yīng)用,首先,介紹了AI大模型服務(wù)的兩種實現(xiàn)方式,選擇使用ollama進(jìn)行部署,隨后,通過SpringBoot+SpringAI來實現(xiàn)應(yīng)用構(gòu)建,本文為開發(fā)者提供了一個實用的指南,幫助他們快速入門生成式AI應(yīng)用的開發(fā)
    2024-11-11
  • Spring MVC 中 AJAX請求并返回JSON的示例

    Spring MVC 中 AJAX請求并返回JSON的示例

    本篇文章主要介紹了Spring MVC 中 AJAX請求并返回JSON,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01

最新評論