Controllo dell'ordine di creazione bean con annotazione @DependsOn

1. Panoramica

Spring, per impostazione predefinita, gestisce il ciclo di vita dei bean e organizza il loro ordine di inizializzazione.

Ma possiamo ancora personalizzarlo in base alle nostre esigenze. Possiamo scegliere l' interfaccia SmartLifeCycle o l' annotazione @DependsOn per la gestione dell'ordine di inizializzazione .

Questo tutorial esplora l' annotazione @DependsOn e il suo comportamento in caso di bean mancante o dipendenza circolare. O nel caso in cui sia semplicemente necessario inizializzare un bean prima di un altro.

2. Maven

Prima di tutto, importiamo la dipendenza dal contesto primaverile nel nostro file pom.xml . Dovremmo sempre fare riferimento a Maven Central per l'ultima versione delle dipendenze:

 org.springframework spring-context 5.2.8.RELEASE 

3. @DependsOn

Dovremmo usare questa annotazione per specificare le dipendenze dei bean. Spring garantisce che i bean definiti verranno inizializzati prima di tentare un'inizializzazione del bean corrente.

Supponiamo di avere un FileProcessor che dipende da FileReader e FileWriter . In questo caso, FileReader e FileWriter dovrebbero essere inizializzati prima del FileProcessor .

4. Configurazione

Il file di configurazione è una pura classe Java con annotazione @Configuration :

@Configuration @ComponentScan("com.baeldung.dependson") public class Config { @Bean @DependsOn({"fileReader","fileWriter"}) public FileProcessor fileProcessor(){ return new FileProcessor(); } @Bean("fileReader") public FileReader fileReader() { return new FileReader(); } @Bean("fileWriter") public FileWriter fileWriter() { return new FileWriter(); } }

FileProcessor specifica le sue dipendenze con @DependsOn . Possiamo anche annotare un componente con @DependsOn:

@Component @DependsOn({"filereader", "fileWriter"}) public class FileProcessor {}

5. Utilizzo

Creiamo un file di classe . Ciascuno dei fagioli aggiorna il testo all'interno di File . FileReader lo aggiorna come letto. FileWriter lo aggiorna come scrittura e FileProcessor aggiorna il testo come elaborato:

@Test public void WhenFileProcessorIsCreated_FileTextContains_Processed() { FileProcessor processor = context.getBean(FileProcessor.class); assertTrue(processor.process().endsWith("processed")); }

5.1. Dipendenza mancante

In caso di dipendenza mancante, Spring genera un'eccezione BeanCreationException con un'eccezione di base NoSuchBeanDefinitionException . Ulteriori informazioni su NoSuchBeanDefinitionException qui.

Ad esempio, il bean dummyFileProcessor dipende da un bean dummyFileWriter . Poiché dummyFileWriter non esiste, genera BeanCreationException:

@Test(expected=NoSuchBeanDefinitionException.class) public void whenDependentBeanNotAvailable_ThrowsNosuchBeanDefinitionException(){ context.getBean("dummyFileProcessor"); }

5.2. Dipendenza circolare

Inoltre, in questo caso, lancia BeanCreationException ed evidenzia che i bean hanno una dipendenza circolare:

@Bean("dummyFileProcessorCircular") @DependsOn({"dummyFileReaderCircular"}) @Lazy public FileProcessor dummyFileProcessorCircular() { return new FileProcessor(file); }

Le dipendenze circolari possono verificarsi se un bean ha un'eventuale dipendenza da se stesso , creando un cerchio:

Bean1 -> Bean4 -> Bean6 -> Bean1

6. Punti chiave

Infine, ci sono alcuni punti di cui dovremmo occuparci durante l'utilizzo dell'annotazione @DependsOn :

  • Durante l'utilizzo di @DependsOn, dobbiamo utilizzare la scansione dei componenti
  • Se una classe DependsOn -annotated viene dichiarata tramite XML, i metadati dell'annotazione DependsOn vengono ignorati

7. Conclusione

@DependsOn diventa particolarmente utile quando si creano sistemi con requisiti di dipendenza complessi.

Facilita l'iniezione delle dipendenze, assicurando che Spring abbia gestito tutte le inizializzazioni di quei Beans richiesti prima di caricare la nostra classe dipendente.

Come sempre, il codice può essere trovato su GitHub.