通过注释实现@Autowired @Lazy @Components的最佳方式?

Rob*_*ram 30 java spring lazy-loading

有没有办法通过注释进行仍在工厂中的@Lazy加载?我发现的问题是,通过在工厂中自动装配我的惰性组件,它们将在加载工厂后立即实例化,从而否定惰性注释.@Component@Autowired

我已经定义了几个懒豆,比如

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

@Component
@Lazy
public final class CloseableFirefoxWebDriver
      extends FirefoxDriver
      implements DisposableBean {
...
}
Run Code Online (Sandbox Code Playgroud)

重要的是他们懒惰,因为

  • 只要创建其中一个,就会弹出浏览器窗口.
  • 我的数据驱动测试可能需要也可能不需要任何一个或全部,即一次运行可能都是Firefox,或者可能需要Firefox和Chrome.
  • 这更重要,因为事实上我有六个这样的bean - Firefox,Chrome,IE,远程Firefox,远程Chrome,远程IE.
  • 所以,如果我的测试只使用其中一个,那么我只希望显示一个浏览器,而不是所有它们.

我有一个工厂用于获取所请求的浏览器,但我第一次尝试此操作失败,因为无论何时任何类使用工厂,所有自动装配的bean都会立即实例化,无论它们是否实际被请求.我理解这是因为一旦实例化了类,它必须实例化属于它的所有实例变量.

@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.
   }
}
Run Code Online (Sandbox Code Playgroud)

所以这是我的第二种方法,即通过应用程序上下文请求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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这种方法实现了我的目标,但我觉得它确实否定了使用注释的有用性.是否有纯粹基于注释的方法来实现这一目标?

  • JDK 6
  • Spring 3.2.6.RELEASE
  • 没有xml,只是注释.

Bij*_*men 51

你必须@Lazy在你的组件上有一个注释@Autowired.这是因为如果你没有@Lazy你的组件,那么它会被急切地创建为一个bean,如果你没有@Lazyon @Autowired然后你再次热切地创造并注入豆子.所以尝试以下它应该只是工作:

@Component
public final class WebDriverFactory {
   @Autowired @Lazy
   private CloseableChromeWebDriver chromeWebDriver;
   @Autowired @Lazy
   private CloseableFirefoxWebDriver firefoxWebDriver;
Run Code Online (Sandbox Code Playgroud)

  • 所以,总而言之,如果我可以转移到 Spring 4,`@Autowired @Lazy` 正是我想要的。如果我必须继续使用 Spring 3,我很高兴继续使用 `appContext.getBean(..)` 作为妥协。所以,谢谢@Biju! (2认同)