簡體   English   中英

在Spring中創建新實例和使用范圍原型注釋之間的區別

[英]Difference between creating new instance and using scope prototype annotation in Spring

我的應用程序正在監聽交換(使用rabbitMQ ),希望接收一些API數據,然后將其重定向到相關位置。

我正在使用rxJava來訂閱這些更改,當目的是打開一個新線程並通過每次創建RestClient發送請求時 - >它將接收數據,解析它,發送它然后將響應發送回隊列。

我的問題是我希望每次都能創建一個RestClient的新實例。 考慮使用Springs Scope注釋: @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)但似乎無法理解如何使用它,如果我每次都使用new RestClient會有什么不同。

你能解釋一下使用getBean不是使用new的好處嗎?

這是代碼:

class MyManager {

   @Autowired
   private WebApplicationContext context;
    ....
    ...
    ...

    @PostConstruct
    myListener.subscribeOn(Schedulers.computation()).subscribe(this::handleApiRequest);


    private void  handleApiRequest(ApiData apiData){

    // Option 1:
    RestClient client = new RestClient();
    client.handleApiRequest(apiData);

    //Option 2:
    // use somehow the prototype?
    RestClient x = (RestClient)context.getBean("restTest")..
    }
}



 @Service
 //@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
 private String server;
  private RestTemplate rest;
  private HttpHeaders headers;
  ResponseEntity<String> responseEntity;

  @PostConstruct
  private void updateHeaders() {
    headers.add(Utils.CONTENT_TYPE, Utils.APPLICATION_JSON);
    headers.add(Utils.ACCEPT, Utils.PREFIX_ALL);
  }


  public void handleApiRequest(ApiData apiRequest) {
    sendRequest(apiRequest); //implemented
    sendResponse(); //implemented
  }


}


  @Bean(name = "restTest")
  @Scope("prototype")
  public RestClient getRestTemplate() {
    return new RestClient();
  }

首先,resttemplate是線程安全的 不要根據請求或使用新關鍵字(構造函數)對其進行實例化,這是一個糟糕的設計。 因為你在這里注釋掉了@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) ; 默認情況下,spring將創建一個RestClient的單例bean,無論你在哪里自動裝配,你都會得到相同的RestClient實例; 所以你做得對

@Service
 //@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {

我在這里有一個問題,在RestClient中,你在哪里實例化private RestTemplate rest; 我在你發布的代碼中沒有看到這一點

如果您按照建議從原型范圍轉移到單例范圍,則可以使用@Autowired RestClient restClient;

代替

@Autowired private WebApplicationContext context;
RestClient x = (RestClient)context.getBean("restTest")

更少的樣板。

當你使用context.getBean ,返回的實例是一個Spring bean,spring處理依賴注入,配置,生命周期回調....... 當你剛剛使用new創建它時,沒有發生這種情況。 在您給出的示例中,只有在使用context.getBean才會調用@PostConstruct方法。

當您使用context.getBean()返回的任何bean時,該bean的生命周期將由Spring處理。

但是如果用新實例初始化bean,則負責創建對象及其生命周期。 (因此@PostConstruct和該類中的其他spring注釋將毫無意義。)並且不會注入該bean中的任何依賴項。

暫無
暫無

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

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