Управление порядком создания бина с помощью аннотации @DependsOn

Управление порядком создания бина с помощью аннотации @DependsOn

1. обзор

Spring по умолчанию управляет жизненным циклом бинов и упорядочивает их порядок инициализации.

Но мы все еще можем настроить его в зависимости от наших потребностей. We can choose either the SmartLifeCycle interface or the @DependsOn annotation for managing initialization order.

В этом руководстве рассматривается аннотация@DependsOn и ее поведение в случае отсутствия bean-компонента илиcircular dependency. Или в случае простой необходимости инициализации одного компонента перед другим.

2. специалист

Прежде всего, давайте импортируем зависимость Spring-context в наш файлpom.xml. Мы всегда должны обращаться к Maven Central дляthe latest version зависимостей:


    org.springframework
    spring-context
    5.1.4.RELEASE

3. @DependsOnс

Мы должны использовать эту аннотацию для определения зависимостей бина. Spring guarantees that the defined beans will be initialized before attempting an initialization of the current bean.с

Допустим, у нас естьFileProcessor, который зависит от aFileReader иFileWriter. В этом случаеFileReader иFileWriter должны быть инициализированы доFileProcessor.

4. конфигурация

Файл конфигурации представляет собой чистый класс Java с аннотацией@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. Мы также можем аннотироватьComponent с помощью@DependsOn:

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

5. использование

Создадим один классFile. Каждый из bean-компонентов обновляет текст в пределахFile. FileReader обновляет его как прочитанное. FileWriter обновляет его как запись, аFileProcessor обновляет текст как обработанный:

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

5.1. Отсутствует зависимость

В случае отсутствия зависимости Spring выдаетBeanCreationException с базовым исключениемNoSuchBeanDefinitionException. Узнать больше оNoSuchBeanDefinitionExceptionhere.

Например, bean-компонентdummyFileProcessor зависит от bean-компонентаdummyFileWriter. ПосколькуdummyFileWriter не существует, он выдаетBeanCreationException:

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

5.2. Круговая зависимость

Кроме того, в этом случае он выдаетBeanCreationException и подчеркивает, что bean-компоненты имеют циклическую зависимость:

@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, создавая круг:

Bean1 -> Bean4 -> Bean6 -> Bean1

6. Ключевые моменты

Наконец, есть несколько моментов, о которых мы должны позаботиться при использовании аннотации@DependsOn:

  • При использовании@DependsOn, мы должны использовать сканирование компонентов

  • Если аннотированный классDependsOn объявлен через XML, метаданные аннотацииDependsOn игнорируются

7. Заключение

@DependsOn становится особенно полезным при создании систем со сложными требованиями к зависимостям.

Это облегчает внедрение зависимостей, гарантируя, что Spring выполнит всю инициализацию требуемых компонентов перед загрузкой нашего зависимого класса.

Как всегда, код можно найтиover on GitHub.