簡體   English   中英

Spring @Autowired - 實例化新bean

[英]Spring @Autowired - Instantiate new bean

需要一些Spring自動裝配和范圍的幫助。

這是基本的app結構:

  1. 我有一個CustomHttpClient,注釋為@Component,還從application.properties文件中提取一些與配置相關的屬性(通過@Value注釋)。

  2. CustomHttpClient由我的應用程序中的多個服務使用。 每當我使用CustomHttpClient時,我通過以下方式自動裝配該實例:

     @Autowired private CustomHttpClient httpClient; 
  3. 我使用攔截器來修改CustomHttpClient中的一些變量,如下所示:

     public class MyInterceptor extends HandlerInterceptorAdapter { @Autowired CustomHttpClient httpClient; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { httpClient.setSomeProperty(newValue); ... 

現在,這是問題所在。 如果我按照上面的描述設置了所有內容,那么每當我通過攔截器更改CustomHttpClient的任何設置時,只要VM正在運行,就會為所有其他客戶端保留該新值。 因此,當我運行httpClient.setSomeProperty()時 - 該設置現在已永久保存。 即使我從另一個客戶端連接到該應用程序。

基本上我需要的是兩件事:

  1. 仍然能夠通過攔截器覆蓋CustomHttpClient的默認設置(請求攔截器,通過配置)。
  2. 確保為每個請求創建一個新的CustomHttpClient實例(在攔截器執行其魔法之后)。

我嘗試將CustomHttpClient的范圍更改為@Scope(“prototype”),但這樣我就無法再使用攔截器更改CustomHttpClient的設置。

默認情況下,使用@Autowired spring bean的范圍是singleton。 這意味着當你使用@Autowired ,spring會注入相同的單例對象。 通過制作范圍prototype您指示Spring為每個@Autowired注入創建新對象,因此在您的攔截器中將擁有自己的HttpClient副本,並且無法查看其他HttpClient對象。

因此,更好的方法是使用單例范圍,使用請求屬性或threadlocal在請求線程中隨身攜帶自定義屬性。 即,不是在攔截器中修改HttpClient屬性,只需設置一些請求屬性或threadlocals並在CustomHttpClient類方法中處理這些自定義設置。

如果你的攔截器只是添加一些屬性,那么使用本地線程應該是更好的選擇。 您可以調用ThreadLocal.set(自定義Map)並在運行線程的任何位置使用它,當程序要離開控制器時,您可以調用ThreadLocal.Unset來清除存儲的值。

這樣你每次都不需要一個新的HttpcLient實例,每次都是一個新的實例將是一個嚴重的缺陷。 並且您將能夠在正在運行的線程中的任何位置使用自定義地圖。

通過XML或注釋支持在Spring容器中聲明的所有bean都是默認的單例。 如果將具有設置為原型的范圍的bean注入單個例如控制器,它將僅注入一次。 有一種方法可以實現這一目標。 這是你應該如何聲明作為原型的bean。 這意味着每次從容器調用此bean時,容器將始終為您提供一個新實例。

<bean id="shoppingCart" class="example.ShoppingCart" scope="request">
     <aop:scoped-proxy />
</bean>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM