2014-10-22 13 views
22

Có cách nào để có @Lazy tải @Component s vẫn là @Autowired trong nhà máy qua chú thích không? Vấn đề tôi thấy là bằng cách autowiring thành phần lười biếng của tôi trong nhà máy, tất cả chúng sẽ được instantiated ngay lập tức một khi nhà máy được nạp, phủ nhận chú thích lười biếng.Cách tốt nhất để đạt được @Autowired @Lazy @Components qua chú thích?

tôi đã xác định nhiều đậu lười biếng như

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

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

Điều quan trọng là họ được lười biếng vì

  • Bất cứ khi nào một trong số họ được tạo ra, cửa sổ trình duyệt bật lên.
  • kiểm tra theo hướng dữ liệu của tôi có thể hoặc không yêu cầu bất kỳ một hoặc tất cả chúng, tức là một lần chạy có thể là tất cả Firefox hoặc có thể yêu cầu Firefox và Chrome.
  • điều này quan trọng hơn vì trên thực tế tôi có sáu loại đậu như vậy - Firefox, Chrome, IE, Firefox từ xa, Chrome từ xa, IE từ xa.
  • Vì vậy, nếu các thử nghiệm của tôi chỉ sử dụng một trong số chúng, thì tôi chỉ muốn một trình duyệt hiển thị chứ không phải tất cả chúng.

Tôi có một Nhà máy để nhận trình duyệt được yêu cầu, nhưng lần đầu tiên tôi thất bại vì bất cứ khi nào bất kỳ lớp nào sử dụng nhà máy, tất cả các bean tự động được khởi tạo ngay lập tức, bất kể chúng có thực sự được yêu cầu hay không. Tôi hiểu điều này là bởi vì một khi lớp được khởi tạo, nó phải khởi tạo tất cả các biến cá thể thuộc về nó.

@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. 
    } 
} 

Vì vậy, đây là cách tiếp cận thứ hai của tôi là để đảm bảo tải lười biếng bằng cách yêu cầu các đậu qua bối cảnh ứng dụng:

@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; 
    } 
} 

Cách tiếp cận này đạt được mục tiêu của tôi, nhưng tôi cảm thấy nó thực sự phủ nhận tính hữu ích của bằng cách sử dụng chú thích. Có cách nào dựa trên chú thích thuần túy để đạt được điều này không?

  • JDK 6
  • Xuân 3.2.6.RELEASE
  • Không xml, chỉ cần chú thích.
+0

Chắc chắn thuộc tính '@ Lazy' nằm trên người dùng của bean chứ không phải định nghĩa của bean. Vì vậy, tôi hy vọng bạn đặt '@ Lazy' ở khắp mọi nơi mà cần đậu để được tải lười biếng. Nếu đó là MỌI NGƯỜI, thì hạt sẽ được tạo khi được sử dụng lần đầu tiên. –

+0

@AshleyFrieze Trừ khi tôi đã hiểu lầm những gì bạn đang nói, không có '@ Lazy' không đi trên người dùng của đậu .. Từ [@Lazy Javadoc] (http://docs.spring.io/spring/docs /current/javadoc-api/org/springframework/context/annotation/Lazy.html): _May được sử dụng trên bất kỳ lớp nào được viết trực tiếp hoặc gián tiếp với @Component hoặc trên các phương thức được chú thích với @Bean ....Nếu hiện tại và được đặt thành true, @Bean hoặc @Component sẽ không được khởi tạo cho đến khi được tham chiếu bởi một bean khác hoặc được truy lục rõ ràng từ BeanFactory._ –

+0

@AshleyFrieze, trong Spring 4, bạn thực sự đúng, theo câu trả lời của Biju .. cảm ơn. :) –

Trả lời

29

Bạn phải có @Lazy chú thích về thành phần của bạn cũng tại điểm mà nó là @Autowired. Điều này là bởi vì nếu bạn không có @Lazy trên thành phần của bạn, sau đó nó được hăm hở tạo ra như một hạt đậu, và nếu bạn không có một @Lazy trên @Autowired của bạn thì một lần nữa nó được háo hức tạo ra và tiêm vào đậu. Vì vậy, hãy thử những điều sau và nó chỉ hoạt động:

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

Tôi khá chắc chắn rằng cần Spring 4, như tôi đã đọc về đêm cuối cùng ở đây: http://zezutom.blogspot.com.au/2014/01/spring-series-part-4-lazy-on- injection.html. Chúng tôi đang sử dụng Spring 3 atm, tuy nhiên cùng một trang có vẻ như để giải thích làm thế nào để đạt được hiệu quả tương tự với nhà cung cấp. Tôi đã không thử điều đó bởi vì thẳng thắn tôi đã không hiểu được nó. –

+0

OK, tôi đã thử nghiệm điều này .. Tôi không thể sử dụng '@Autowired @ Lazy' với Spring 3, nhưng tôi có thể làm việc với Spring 4 - và nó hoạt động hoàn hảo. Tôi cũng dành thời gian tìm hiểu cách sử dụng 'javax.inject.Inject' và' javax.inject.Provider' như [Tom's Blog] (http://zezutom.blogspot.com.au/2014/01/spring- series-part-4-lazy-on-injection.html) được mô tả, nhưng nó chỉ mất quá nhiều mã bổ sung vì tôi sẽ phải viết một kiểu 'Nhà cung cấp' cho mọi trình điều khiển web đơn vì chúng là mỗi lớp khác nhau. –

+1

Vì vậy, kết luận, nếu tôi có thể chuyển sang Spring 4, '@Autowired @ Lazy' thực hiện chính xác những gì tôi muốn. Nếu tôi phải ở lại với Spring 3, tôi hạnh phúc, đủ để tiếp tục sử dụng 'appContext.getBean (..)' như một sự thỏa hiệp. Vì vậy, cảm ơn @Biju! –

Các vấn đề liên quan