Как в микросервисной архитектуре выбирать разные реализации интерфейса в разных сервисах
Что проверяют
Понимаете ли вы разницу между выбором реализации внутри одного приложения и контрактом между сервисами. Следом обычно спрашивают, как переключить реализацию без пересборки и почему бы не положить интерфейс в общий jar.
Как отвечать
Сначала разведите два уровня. Между сервисами контракт это не Java-интерфейс, а API: OpenAPI для REST, .proto для gRPC, схема события в Kafka. Каждый сервис владеет своей реализацией, общий код с бизнес-логикой в микросервисах стараются не заводить.
Внутри сервиса выбор реализации это задача Spring:
@ConditionalOnProperty: бин создаётся по свойству, напримерpayment.provider=stripeвapplication.ymlконкретного сервиса. Один код, разное поведение по конфигурации;@Qualifierи@Primary: когда реализаций несколько и в конкретном месте нужна конкретная;- стратегия через
Map<String, PaymentGateway>: Spring внедряет все реализации с ключами по именам бинов, выбор идёт в рантайме по ключу из запроса. Подходит, когда разные клиенты платят разными способами; @Profile: только для окружений, например заглушка вместо внешнего API в тестах.
Если общая библиотека всё же нужна, например клиент к внутренней шине, её оформляют как Spring Boot starter с автоконфигурацией. Классы регистрируются в META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, реализация по умолчанию помечается @ConditionalOnMissingBean, и сервис подменяет её своим бином. Свойства можно раздавать централизованно через Spring Cloud Config, но смена бина всё равно требует перезапуска. На лету переключаются только стратегия или фиче-флаг.
Где спотыкаются
Выносят интерфейсы и реализации для всех сервисов в один общий jar. Любая правка требует синхронного релиза, и получается распределённый монолит.
Регистрируют две реализации без квалификатора, получают NoUniqueBeanDefinitionException при старте и лечат это цепочкой if по типу вместо стратегии.
Ставят @ConditionalOnMissingBean в обычную пользовательскую конфигурацию. Условие проверяется в момент обработки класса, и результат зависит от порядка регистрации бинов. Документация Spring Boot советует применять его только в автоконфигурации.