Le meilleur moyen de réaliser @Autowired @Lazy @Components via des annotations?

Existe-t-il un moyen d’avoir @Lazy train de charger des @Component s qui sont toujours @Autowired dans une usine via des annotations? Le problème que j’ai trouvé est qu’en envoyant mes composants paresseux en usine, ils seront tous instanciés immédiatement après le chargement de la fabrique, annulant ainsi l’annotation différée.

J’ai défini plusieurs haricots paresseux tels que

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

Il est important qu’ils soient paresseux car

  • Chaque fois que l’un d’eux est créé, la fenêtre du navigateur apparaît.
  • Mes tests basés sur les données peuvent nécessiter ou non l’un ou l’ensemble d’entre eux, c’est-à-dire qu’une exécution peut concerner tout Firefox, ou peut nécessiter Firefox et Chrome.
  • C’est plus important car en fait, je possède six beans de ce type: Firefox, Chrome, IE, Firefox à distance, Chrome distant, IE à distance.
  • Donc, si mes tests n’en utilisent qu’un, alors je ne veux que ce navigateur, pas tous.

J’ai une Factory pour obtenir le navigateur demandé, mais ma première tentative a échoué car chaque fois qu’une classe utilisait la fabrique, tous les beans autowired étaient immédiatement instanciés, qu’ils aient été réellement demandés ou non. Je comprends que c’est parce qu’une fois la classe instanciée, elle doit instancier toutes les variables d’instance qui lui appartiennent.

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

Voici donc ma deuxième approche qui consiste à garantir un chargement paresseux en demandant le bean via le contexte d’application:

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

Cette approche atteint mon objective, mais j’estime que cela nie vraiment l’utilité d’utiliser des annotations. Existe-t-il un moyen purement basé sur des annotations pour y parvenir?

  • JDK 6
  • Spring 3.2.6.LELEASE
  • Pas de xml, juste des annotations.

Vous devez également avoir l’annotation @Lazy sur votre composant au point où il est @Autowired in. En effet, si vous n’avez pas @Lazy sur votre composant, il est créé avec impatience sous la forme d’un haricot, et si n’avez pas de @Lazy sur votre @Autowired mais il est à nouveau créé et injecté avec impatience dans le haricot. Donc, essayez ce qui suit et cela devrait fonctionner:

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