Что такое циклическая зависимость (circular dependency) в Spring и как ее обработать?

«Что такое циклическая зависимость (circular dependency) в Spring и как ее обработать?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Циклическая зависимость возникает, когда два бина зависят друг от друга (Bean A → Bean B → Bean A). По умолчанию Spring выбрасывает BeanCurrentlyInCreationException.

Пример проблемы:

@Component
class ServiceA {
    @Autowired
    private ServiceB serviceB; // Зависит от B
}

@Component
class ServiceB {
    @Autowired
    private ServiceA serviceA; // Зависит от A -> Цикл!
}

Способы решения:

  1. Использование @Lazy: Откладывает создание прокси для одной из зависимостей до первого использования.
    @Component
    class ServiceA {
        @Autowired
        @Lazy
        private ServiceB serviceB;
    }
  2. Setter/Field Injection вместо Constructor Injection: Позволяет Spring создать бины, а затем внедрить зависимости.
  3. Рефакторинг архитектуры: Лучший подход — устранить цикл, введя третий компонент или изменив ответственность классов.