Contrôle de l’ordre de création des beans avec l’annotation @DependsOn

Contrôle de l'ordre de création de beans avec l'annotation @DependsOn

1. Vue d'ensemble

Spring, par défaut, gère le cycle de vie des beans et organise leur ordre d'initialisation.

Mais nous pouvons toujours le personnaliser en fonction de nos besoins. We can choose either the SmartLifeCycle interface or the @DependsOn annotation for managing initialization order.

Ce tutoriel explore l'annotation@DependsOn et son comportement en cas de bean manquant oucircular dependency. Ou si vous avez simplement besoin d'un haricot initialisé avant un autre.

2. Maven

Tout d’abord, importons la dépendance de contexte de ressort dans notre fichierpom.xml. Nous devrions toujours nous référer à Maven Central pour lesthe latest version de dépendances:


    org.springframework
    spring-context
    5.1.4.RELEASE

3. @DependsOn

Nous devrions utiliser cette annotation pour spécifier les dépendances de bean. Spring guarantees that the defined beans will be initialized before attempting an initialization of the current bean.

Disons que nous avons unFileProcessor qui dépend de aFileReader etFileWriter. Dans ce cas,FileReader etFileWriter doivent être initialisés avant lesFileProcessor.

4. Configuration

Le fichier de configuration est une classe Java pure avec l'annotation@Configuration:

@Configuration
@ComponentScan("com.example.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 specifies its dependencies with @DependsOn. On peut aussi annoter unComponent avec@DependsOn:

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

5. Usage

Créons une classeFile. Chacun des beans met à jour le texte dans lesFile. FileReader le met à jour comme lu. FileWriter le met à jour en écriture etFileProcessor met à jour le texte comme traité:

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

5.1. Dépendance manquante

En cas de dépendance manquante, Spring lance unBeanCreationException avec une exception de base deNoSuchBeanDefinitionException. En savoir plus surNoSuchBeanDefinitionExceptionhere.

Par exemple, le beandummyFileProcessor dépend d'un beandummyFileWriter. PuisquedummyFileWriter n’existe pas, il renvoieBeanCreationException:

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

5.2. Dépendance Circulaire

De plus, dans ce cas, il jetteBeanCreationException et met en évidence que les beans ont une dépendance circulaire:

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

Circular dependencies can happen if a bean has an eventual dependency on itself, création d'un cercle:

Bean1 -> Bean4 -> Bean6 -> Bean1

6. Points clés

Enfin, il y a quelques points à prendre en compte lors de l'utilisation de l'annotation@DependsOn:

  • Lors de l'utilisation de@DependsOn,, nous devons utiliser l'analyse des composants

  • Si une classe annotéeDependsOn est déclarée via XML, les métadonnées d'annotationDependsOn sont ignorées

7. Conclusion

@DependsOn devient particulièrement utile lors de la construction de systèmes avec des exigences de dépendance complexes.

Cela facilite l’injection de dépendance, en garantissant que Spring aura géré l’ensemble de l’initialisation de ces Beans requis avant de charger notre classe dépendante.

Comme toujours, le code peut être trouvéover on GitHub.