Is there a way to have @Lazy
loading @Component
s that are still @Autowired
in a factory via annotations? The problem I found is that by autowiring my lazy components in the factory, they will all be instantiated immediately once the factory is loaded, negating the lazy annotation.
I have defined several lazy beans such as
@Component
@Lazy
public final class CloseableChromeWebDriver
extends ChromeDriver
implements DisposableBean {
...
}
@Component
@Lazy
public final class CloseableFirefoxWebDriver
extends FirefoxDriver
implements DisposableBean {
...
}
It is important that they be lazy because
I have a Factory for getting the requested browser, but my first attempt at this failed because whenever any class used the factory, all of the autowired beans were being instantiated straight away, irrespective of whether they were actually requested. I understand this is because once the class is instantiated, it must instantiate all of the instance variables belonging to it.
@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.
}
}
So here is my second approach which is to ensure lazy loading by requesting the bean through the application context:
@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;
}
}
This approach achieves my goal, but I feel it really negates the usefulness of using annotations. Is there a purely annotation based way to achieve this?
You have to have @Lazy
annotation on your component as well at the point where it is @Autowired
in. This is because if you don't have @Lazy
on your component, then it is eagerly created as a bean, and if you have don't have an @Lazy
on your @Autowired
then again it is eagerly created and injected into the bean. So try the following and it should just work:
@Component
public final class WebDriverFactory {
@Autowired @Lazy
private CloseableChromeWebDriver chromeWebDriver;
@Autowired @Lazy
private CloseableFirefoxWebDriver firefoxWebDriver;