--- aliases: tags: - maturity/🌱 date: - - 2023-11-20 zero-link: - "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]" parents: linked: --- Циклические зависимости между сервисами возникают, когда сервисы взаимно внедряются друг в друга. Например, сервис А внедряет сервис Б, но в тоже время сервис Б внедряет сервис А. В этом случае [SpringBoot](../../meta/zero/00%20SpringBoot.md) и [Quarkus](../../meta/zero/00%20Quarkus.md) не знают, как создать такие бины и внедрить их друг в друга. > [!WARNING] > Обычно такая ситуация сигнализирует о плохо продуманной архитектуре приложения. Пример циклической зависимости в Spring: ```java @Service public class ServiceOne { private final ServiceTwo serviceTwo; public ServiceOne(ServiceTwo serviceTwo) { this.serviceTwo = serviceTwo; } } ``` ```java @Service public class ServiceTwo { private final ServiceOne serviceOne; public ServiceTwo(ServiceOne serviceOne) { this.serviceOne = serviceOne; } } ``` Вот что вы можете с этим сделать: ## Пересмотреть архитектуру приложения ==Это предпочтительный вариант.== Возможно вам стоит создать сервис В, который внедрит в себя сервисы А и Б. В таком случае вы распутаете циклическую зависимость. ```java @Service public class ServiceThree { private final ServiceOne serviceOne; private final ServiceTwo serviceTwo; public ServiceThree(ServiceOne serviceOne, ServiceTwo serviceTwo) { this.serviceOne = serviceOne; this.serviceTwo = serviceTwo; } } ``` ```java @Service public class ServiceOne { } ``` ```java @Service public class ServiceTwo { } ``` ## Ленивое внедрение В Spring вы можете указать аннотацию `@Lazy` у аргумента конструктора одного их сервисов. Таким образом сначала будет создан один сервис, для второго сервиса спринг создаст прокси класс, создаст из него бин и внедрит его в ваш сервис. После чего создаст второй сервис и внедрит туда уже созданный первый. А далее заменит ссылку с прокси объекта на второй сервис. ```java @Service public class ServiceTwo { private final ServiceOne serviceOne; public ServiceTwo(@Lazy ServiceOne serviceOne) { this.serviceOne = serviceOne; } } ``` ```java @Service public class ServiceOne { private final ServiceTwo serviceTwo; public ServiceOne(ServiceTwo serviceTwo) { this.serviceTwo = serviceTwo; } } ``` ## Внедрение через Setter Внедрить один из сервисов через сеттер, вместо конструктора. Таким образом, фреймворк сможет создать оба бина, а потом уже внедрит один в другой. ```java @Service public class ServiceOne { private final ServiceTwo serviceTwo; public ServiceOne(ServiceTwo serviceTwo) { this.serviceTwo = serviceTwo; } } ``` ```java @Service public class ServiceTwo { private ServiceOne serviceOne; @Autowired public void setServiceOne(ServiceOne serviceOne) { this.serviceOne = serviceOne; } } ``` *** ## Мета информация **Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] **Родитель**:: **Источник**:: **Автор**:: **Создана**:: [[2023-11-20]] ### Дополнительные материалы - ### Дочерние заметки