Springboot重新加載Bean


https://www.cnblogs.com/Chaos1973-newWorld/p/15031018.html

 

參考:

Java DefaultListableBeanFactory.destroyBean方法代碼示例

https://vimsky.com/examples/detail/java-method-org.springframework.beans.factory.support.DefaultListableBeanFactory.destroyBean.html

 

 

 

 

Springboot重新加載Bean

背景:

       有一個需求是要獲取第三方的接口,加載到本地,通過本地調用接口獲取結果,第三方接口會有版本變動,前端會有點擊事件獲取最新版本。

設計:

      考慮到並不是每次都需要重新獲取第三方接口,我將第三方接口以Configuration和bean的形式放入配置類中,示例代碼如下:

復制代碼
@Configuration
public class DemoConfiguration {
    @Bean(name="execute")
    public static Execute getBean(){
        //TODO
//Execute是我邏輯中需要的類
Execute execute = ....(邏輯過程省略)
return execute; } }
復制代碼

      后續的問題是,當第三方版本變動的時候,不能通過重啟服務獲取新的版本,而是重新加載配置類,獲取新的實例,經過多方查找資料,匯總如下:

復制代碼
mport org.springframework.context.ApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class DemoController {
    @Autowired
    private ApplicationContext applicationContext;
    @ResponseBody
    @PostMapping("/getVersion")
    public void reloadInstance(){
        //獲取上下文
        DefaultListableBeanFactory defaultListableBeanFactory =
                (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
        //銷毀指定實例 execute是上文注解過的實例名稱 name="execute"
        defaultListableBeanFactory.destroySingleton("execute");
        //按照舊有的邏輯重新獲取實例,Excute是我自己邏輯中的類
        Execute execute = DemoConfiguration.getBean();
        //重新注冊同名實例,這樣在其他地方注入的實例還是同一個名稱,但是實例內容已經重新加載
        defaultListableBeanFactory.registerSingleton("execute",execute);
    }

}
復制代碼

經過驗證可行。

 

_________________________________________________________________________________________________________________

 

Spring2.0 新特性之Bean新增范圍session, request, global session

 

      在Spring2.0之前,我們對Bean的控制僅有兩種:singleton和prototype。Spring默認的Bean是為singleton,在實際項目中,一般與狀態無關的Bean,都可以使用singleton;

而那些與具體狀態相關的Bean,則應該顯示的在Bean定義中設置為singleton=false。


  Spring2.0之前,我們是這么定義的:

      <bean id="singletonBean" class="myBean.singletonBean" />
      <bean id="notSingletonBean" class="myBean.notSingletonBean" singleton="false"/>


  在Spring2.0以后,因為增加了session, request, global session三種Bean的范圍,所以在Bean的配置上,也發生了改變,不過Bean的默認范圍仍然是singleton。
       

  新的寫法如下:

<bean id="newBean" class="myBean.newBean" scope="session | request | global session | singleton | prototype">
<aop:scoped-proxy/>
</bean>


       對於新增加的三種范圍,Spring2.0對Bean的要求就是必須是在web環境中才能定義這三種范圍。對比之前的singletoBean和notSingletonBean的XML定義,我們可以發現<aop:scoped-proxy/> 這個新的配置項。
      那么,這又是怎么一回事呢?
      為了理解為什么需要這一行和以前完全不同的Bean配置,我們需要對Spring2.0實現session, request, global session三種Bean的范圍的原理進行研究。
      可以想象,對於開發人員來說,最重要的是得到一個實例,該實例提供給我們的就是和我們需要的Bean一樣的接口。無論我們定義的Bean的范圍如何,容器都要求可以將正確的實例返回給我們,那么,采用代理機制則可以完成這一個任務。代理機制屏蔽了基於Bean所定義的范圍返回實例的要求,同時可以提供和我們所要求的Bean同樣的接的口。基於這個原理,
為了實現基於作用域機制的Bean的控制,Spring2.0引入了一個新的接口:

 

public interface Scope  {
 Object get(String name, ObjectFactory objectFactory);
 Object remove(String name);

   這個接口是用來表示Bean范圍的接口,而在ConfigurableBeanFactory接口中定義了Bean工廠相關Scope注冊的方法,使得可往Bean工廠中加入新范圍的Bean。

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory,
 void registerScope(String scopeName, Scope scope);
 void destroyScopedBean(String beanName);
}

   同時,Spring2.0在AbstractFactoryBean的getBean方法中實現了對Scope Bean支持以及在WebApplicationContext中注冊session.request,global session三種Scope,這里就不繼續貼代碼了。

   最后需要提醒的是global session是應用於基於portlet的web應用中才有意義。

 

______________________________________________________________________________________________

  在容器ConfigurableBeanFactory接口中定義了Bean工廠有關Scope注冊的相關方法,使得可往Bean工廠中加入新類型的Bean。
  public interface ConfigurableBeanFactory extends HierarchicalBeanFactory,
  void registerScope(String scopeName, Scope scope);//往Bean工廠中添加一個新的范圍(默認只有兩種范圍:singleton及prototype)
  void destroyScopedBean(String beanName);//銷毀B ean工廠中范圍Bean
  }
————————————————————————————————————————————————————


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM