1. Обзор
Spring по умолчанию управляет жизненным циклом бобов и упорядочивает их порядок инициализации.
Но мы все еще можем настроить его в соответствии с нашими потребностями. Мы можем выбрать либо интерфейс SmartLifecycle , либо аннотацию @dependsOn для управления порядком инициализации .
Этот учебник исследует аннотацию @dependsOn и ее поведение в случае отсутствия боба или циклической зависимости . Или в случае просто необходимости инициализации одного из них перед другим.
2. Maven
Прежде всего, давайте импортируем зависимость spring-context в ваш pom.xml файл. Мы всегда должны обращаться к Maven Central за последней версией зависимостей:
org.springframework spring-context 5.2.8.RELEASE
3. @dependsOn
Мы должны использовать эту аннотацию для указания зависимостей бобов. Spring гарантирует, что определенные бобы будут инициализированы перед попыткой инициализации текущего боба.
Допустим, у нас есть Файловый процессор , который зависит от FileReader и FileWriter . В этом случае FileReader и FileWriter должны быть инициализированы перед Файловым процессором .
4. Конфигурация
Файл конфигурации представляет собой чистый класс Java с аннотацией @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(); } }
Файловый процессор определяет свои зависимости с помощью @dependsOn . Мы также можем аннотировать Компонент с помощью @dependsOn:
@Component @DependsOn({"filereader", "fileWriter"}) public class FileProcessor {}
5. Использование
Давайте создадим один класс File . Каждый из бобов обновляет текст внутри File . File Reader обновляет его как прочитанный. FileWriter обновляет его как запись и Файловый процессор обновляет текст как обработанный:
@Test public void WhenFileProcessorIsCreated_FileTextContains_Processed() { FileProcessor processor = context.getBean(FileProcessor.class); assertTrue(processor.process().endsWith("processed")); }
5.1. Отсутствующая Зависимость
В случае отсутствия зависимости Spring выдает исключение BeanCreationException с базовым исключением NoSuchBeanDefinitionException . Подробнее о NoSuchBeanDefinitionException | читайте здесь .
Например, dummy File Processor bean зависит от dummy File Writer bean. Поскольку dummy File Writer не существует, он выдает 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); }
Круговые зависимости могут возникать , если боб имеет возможную зависимость от самого себя , создавая круг:
Bean1 -> Bean4 -> Bean6 -> Bean1
6. Ключевые моменты
Наконец, есть несколько моментов, о которых мы должны позаботиться при использовании @dependsOn аннотации:
- Во время использования @dependsOn, мы должны использовать компонентное сканирование
- Если Зависит от -аннотированный класс объявлен через XML, Зависит от метаданные аннотаций игнорируются
7. Заключение
@dependsOn становится особенно полезным при построении систем со сложными требованиями к зависимостям.
Это облегчает внедрение зависимостей, гарантируя, что Spring обработает всю инициализацию этих необходимых компонентов перед загрузкой нашего зависимого класса.
Как всегда, код можно найти на GitHub .