Как реализовать порядок вызова роботов, если порядок важен?
Что проверяют
Умеете ли вы сделать порядок явной частью дизайна, а не случайным следствием регистрации бинов или работы пула потоков. Следом обычно спрашивают, что делать, если часть роботов можно запускать параллельно, а часть зависит от результатов других.
Как отвечать
Сначала уточните, что за роботы: обработчики одного события, шаги конвейера или независимые задачи. Затем варианты от простого к сложному:
- явный список:
List<Robot>собирается в конфигурации в нужном порядке и обходится обычным циклом. Самое читаемое решение, порядок виден в одном месте; - Spring и
@Order: если роботы это бины одного интерфейса, при внедренииList<Robot>Spring сортирует их по@Orderили интерфейсуOrdered. Меньшее значение идёт раньше, бины без аннотации получаютOrdered.LOWEST_PRECEDENCEи оказываются в конце; - цепочка обязанностей: каждый робот решает, передавать ли управление дальше. Подходит, когда шаг может прервать обработку;
- асинхронно, но по порядку:
CompletableFuture.thenComposeсвязывает шаги, аExecutors.newSingleThreadExecutor()выполняет задачи строго в порядке отправки; - зависимости: если порядок задан графом «B после A и C», стройте DAG и сортируйте его топологически. Независимые ветки тогда можно запускать параллельно.
Отдельно проговорите поведение при сбое: падение одного робота обрывает цепочку или пишется в лог, а цепочка идёт дальше. Это бизнес-решение, и его стоит озвучить вместе с тем, нужны ли повторы и компенсация уже выполненных шагов.
Где спотыкаются
Считают, что @Order управляет порядком создания бинов. Он влияет на сортировку в коллекциях при внедрении, а порядок инициализации синглтонов задают зависимостями или @DependsOn.
Запускают роботов в пуле из нескольких потоков или через parallelStream().forEach и ждут, что порядок сохранится. Порядок завершения при этом не гарантирован: нужен один поток, forEachOrdered или явная сборка результатов по индексу.
Прячут порядок в неявных местах: HashMap, HashSet, порядок сканирования классов. Сегодня всё работает, а после переименования пакета или добавления нового бина роботы молча меняются местами.