Подтвердить что ты не робот

Лучший способ добиться @Autowired @Lazy @Components через аннотации?

Есть ли способ иметь @Lazy загрузку @Component, которые все еще @Autowired в factory через аннотации? Проблема, которую я обнаружил, заключается в том, что путем автообновления моих ленивых компонентов в factory все они будут созданы сразу после загрузки factory, отрицая ленивую аннотацию.

Я определил несколько ленивых beans, таких как

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

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

Важно, чтобы они были ленивыми, потому что

  • Когда создается один из них, открывается окно браузера.
  • Мои тесты, управляемые данными, могут требовать или не требовать ни одного или всех из них, то есть один запуск может быть всем Firefox, или может потребоваться Firefox и Chrome.
  • Это более важно, потому что на самом деле у меня есть шесть таких beans - Firefox, Chrome, IE, Remote Firefox, Remote Chrome, Remote IE.
  • Итак, если мои тесты используют только один из них, тогда я хочу, чтобы этот браузер показывал не все.

У меня есть factory для получения запрошенного браузера, но моя первая попытка этого не удалась, потому что всякий раз, когда какой-либо класс использовал factory, все автоматически создаваемые beans создавались сразу же, независимо от того, были ли они фактически запрошено. Я понимаю, это потому, что как только экземпляр класса создается, он должен создать экземпляр всех принадлежащих ему переменных экземпляра.

@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
  • Spring 3.2.6.RELEASE
  • Нет xml, просто аннотации.
4b9b3361

Ответ 1

Вы должны иметь аннотацию @Lazy на вашем компоненте, а также в точке, где она находится @Autowired. Это связано с тем, что если у вас нет @Lazy на вашем компоненте, то он с нетерпением создается как bean, и если у вас нет @Lazy на вашем @Autowired, то он снова создается и вводится в bean. Поэтому попробуйте следующее, и оно должно просто работать:

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