2014-10-22 46 views
22

有沒有辦法讓@Lazy加載@Component s仍然@Autowired在工廠通過註釋?我發現的問題是,通過在工廠中自動裝配我的懶惰組件,它們將在工廠加載後立即實例化,否定惰性批註。通過註釋實現@Autowired @Lazy @Components的最佳方式是什麼?

我已經定義了幾個懶豆如

@Component 
@Lazy 
public final class CloseableChromeWebDriver 
     extends ChromeDriver 
     implements DisposableBean { 
... 
} 

@Component 
@Lazy 
public final class CloseableFirefoxWebDriver 
     extends FirefoxDriver 
     implements DisposableBean { 
... 
} 

他們偷懶,因爲

  • 每當創建其中之一,瀏覽器窗口會彈出是非常重要的。
  • 我的數據驅動的測試可能需要或可能不需要它們中的任何一個或全部,即一次運行可能是所有Firefox,或者可能需要Firefox和Chrome。
  • 這個更重要,因爲實際上我有6個這樣的豆子 - Firefox,Chrome,IE,Remote Firefox,Remote Chrome,Remote IE。因此,如果我的測試只使用其中一個,那麼我只想讓一個瀏覽器顯示,而不是全部顯示。

我有獲得所請求的瀏覽器一廠,但我在第一次嘗試失敗了,因爲每當任何類使用的工廠,所有的自動裝配豆都被實例化直線距離,而不管他們是否實際請求。我明白這是因爲一旦類被實例化,它就必須實例化屬於它的所有實例變量。

@Component 
public final class WebDriverFactory { 
    @Autowired 
    private CloseableChromeWebDriver chromeWebDriver; 
    @Autowired 
    private CloseableFirefoxWebDriver firefoxWebDriver; 

    public synchronized WebDriver getWebDriver(final Browser browser) { 
    // get whatever webdriver is matched by the enum Browser. 
    } 
} 

因此,這裏是我的第二個途徑是通過應用程序上下文請求bean來保證延遲加載:

@Component 
public final class WebDriverFactory { 
    private CloseableChromeWebDriver chromeWebDriver; 
    private CloseableFirefoxWebDriver firefoxWebDriver; 
    @Autowired 
    private ApplicationContext appContext; 

    public synchronized WebDriver getWebDriver(final Browser browser) { 
     WebDriver driver = null; 
     switch (browser) { 
     case FIREFOX: 
      if (firefoxRemoteWebDriver == null) { 
       firefoxRemoteWebDriver = appContext.getBean("closeableRemoteFirefoxWebDriver", 
        CloseableRemoteFirefoxWebDriver.class); 
      } 
      driver = firefoxRemoteWebDriver; 
      break; 
     // etc... 
     return driver; 
    } 
} 

這種方法實現了我的目標,但我覺得它真的否定的用處使用註釋。有沒有一種純粹的基於註解的方式來實現這一點?

  • JDK 6
  • 春3.2.6.RELEASE
  • 沒有XML,只是註釋。
+0

當然'@ Lazy'屬性在bean的用戶上,而不在bean的定義上。所以我希望你把'@ Lazy'放到需要這個bean被加載的地方。如果那是無處不在,那麼這個bean將在第一次使用時被創建。 – 2014-10-22 09:47:56

+0

@AshleyFrieze除非我誤解了你的意思,否則'@ Lazy'不會在bean的用戶身上..從[@Lazy Javadoc](http://docs.spring.io/spring/docs /current/javadoc-api/org/springframework/context/annotation/Lazy.html):_可以用於任何直接或間接使用@Component註解的類或使用@Bean註釋的方法....如果存在並設置爲true,那麼@Bean或@Component將不會被初始化,直到被另一個bean引用或從封閉的BeanFactory中明確檢索出來的時候。您確實是正確的,按照Biju的回答.. @ – 2014-10-22 10:37:49

+0

@AshleyFrieze,在Spring 4中。那謝謝啦。 :) – 2014-10-22 23:56:17

回答

29

你必須有@Lazy註釋你的組件上,以及在它是@Autowired的點,這是因爲,如果你沒有@Lazy您的組件上做的話,就急切地作爲一個bean創建,如果您的@Autowired上沒有@Lazy,那麼它會再次被急切創建並注入到bean中。因此,請嘗試以下操作,它應該可以正常工作:

@Component 
public final class WebDriverFactory { 
    @Autowired @Lazy 
    private CloseableChromeWebDriver chromeWebDriver; 
    @Autowired @Lazy 
    private CloseableFirefoxWebDriver firefoxWebDriver; 
+0

我相當肯定需要Spring 4,因爲我昨天在這裏閱讀了這篇文章:http://zezutom.blogspot.com.au/2014/01/spring-series-part-4-lazy-on- injection.html。我們使用Spring 3 atm,但是同一頁似乎解釋瞭如何與Provider實現相同的效果。我沒有嘗試過,因爲坦率地說,我還沒有明白。 – 2014-10-22 20:27:57

+0

好的,我測試了這個..我不能在Spring 3中使用'@Autowired @ Lazy',但是我可以使用Spring 4 - 並且它完美地工作。我還花時間瞭解如何使用'javax.inject.Inject'和'javax.inject.Provider'作爲[Tom's Blog](http://zezutom.blogspot.com.au/2014/01/spring-系列部分4 lazy-on-injection.html)描述,但它只是需要太多額外的代碼,因爲我必須爲每個單獨的Web驅動程序編寫'Provider'類型,因爲它們是不同的類。 – 2014-10-22 23:50:08

+1

因此,總而言之,如果我可以遷移到Spring 4,那麼'@Autowired @ Lazy'就是我想要的。如果我必須留在Spring 3中,我很高興繼續使用'appContext.getBean(..)'作爲折衷方案。所以,謝謝@Biju! – 2014-10-22 23:50:37

相關問題