Управление порядком создания бина с помощью аннотации @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.