2015-01-16 86 views
40

我很好奇Spring注入如何處理調用@Bean註釋的方法。如果我在方法上放置了一個@Bean註解並返回一個實例,我知道這告訴spring通過調用方法並獲取返回的實例來創建一個bean。但是,有時該bean必須用於連接其他bean或設置其他代碼。通常的做法是調用@Bean註釋的方法來獲取實例。我的問題是,爲什麼這不會導致bean的多個實例浮動?在Spring java配置中調用@Bean註釋方法

例如,請參閱下面的代碼(取自另一個問題)。 entryPoint()方法註解爲@Bean,所以我想春天會創建一個新的實例BasicAuthenticationEntryPoint作爲一個bean。然後,我們再次在配置塊中調用entryPoint(),但好像entryPoint()返回了這個bean實例,並且沒有多次調用(我試過記錄,只有一個日誌條目)。可能我們可以在配置的其他部分多次調用entryPoint(),並且我們總是會獲得相同的實例。我的理解是正確的嗎?春天做了一些用@Bean註解的方法的魔術改寫嗎?

@Bean 
public BasicAuthenticationEntryPoint entryPoint() { 
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint(); 
    basicAuthEntryPoint.setRealmName("My Realm"); 
    return basicAuthEntryPoint; 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 

    http 
     .exceptionHandling() 
      .authenticationEntryPoint(entryPoint()) 
      .and() 
     .authorizeUrls() 
      .anyRequest().authenticated() 
      .and() 
     .httpBasic();  
} 

回答

61

是的,春天確實有些神奇。檢查Spring Docs

所有@Configuration類在啓動時使用的子類CGLIB。在子類中,child方法在調用父方法並創建新實例之前首先檢查容器是否有緩存的(範圍)Bean。

這意味着您@Bean方法的調用,通過CGLIB代理,因此返回bean的緩存版本(不創建一個新的)。

@Bean s的默認範圍是SINGLETON,如果您指定了不同的範圍,例如PROTOTYPE,則調用將傳遞給原始方法。

+0

是否可以重寫這種方式創建的bean?例如,我有一個Spring定義的類,它直接調用一個bean的創建方法。我想要的是不是使用該方法創建的bean,而是我自己定義的一個bean(通過@ @ @ @和@ @ @ @ @註釋它)。 – Fons