Перейти к основному содержимому

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

· 3 мин. чтения

1. Обзор

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

Но мы все еще можем настроить его в соответствии с нашими потребностями. Мы можем выбрать либо интерфейс SmartLifeCycle , либо аннотацию @DependsOn для управления порядком инициализации .

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

2. Мавен

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

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>

3. @Зависит от

Мы должны использовать эту аннотацию для указания зависимостей компонентов. Spring гарантирует, что определенные bean-компоненты будут инициализированы перед попыткой инициализации текущего bean-компонента.

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

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

Файл конфигурации представляет собой чистый класс Java с аннотацией @Configuration :

@Configuration
@ComponentScan("com.foreach.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 указывает свои зависимости с помощью @DependsOn . Мы также можем аннотировать компонент с помощью @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 . Подробнее о NoSuchBeanDefinitionException читайте здесь .

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

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

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

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

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

Циклические зависимости могут возникать, если bean-компонент имеет возможную зависимость от самого себя , создавая круг:

Bean1 -> Bean4 -> Bean6 -> Bean1

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

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

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

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

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

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

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