Как в Spring автоматически получить все бины, реализующие интерфейс робота?
Что проверяют
Знаете ли вы, что Spring умеет внедрять коллекцию всех бинов нужного типа, и понимаете ли детали: порядок, пустой список, скоупы. Следом обычно спрашивают, как выбрать конкретную реализацию по ключу, то есть собрать паттерн «стратегия».
Как отвечать
Базовый способ: объявить зависимость типа коллекции, и контейнер положит туда все подходящие бины.
List<Robot>: все реализации. Порядок задаётся@Orderили интерфейсомOrdered, без них на порядок лучше не рассчитывать;Map<String, Robot>: ключ это имя бина, значение сама реализация. Удобно для выбора по имени, но надёжнее собрать собственную карту в конструкторе по методу вродеrobot.type(), чтобы не зависеть от имён бинов;ObjectProvider<Robot>: ленивый доступ черезorderedStream(), спокойно переживает отсутствие реализаций и отдаёт свежие экземпляры prototype-бинов при каждом обращении;ApplicationContext.getBeansOfType(Robot.class): работает, но это уже service locator, в бизнес-коде его стоит избегать.
Внедрять лучше через конструктор: public RobotManager(List<Robot> robots). При единственном конструкторе @Autowired не нужен. Отдельная аннотация @ComponentScan в Spring Boot тоже не нужна: она уже входит в @SpringBootApplication и сканирует пакет главного класса и вложенные в него.
Работает и фильтрация: @Qualifier на точке внедрения оставит в коллекции только бины с тем же квалификатором, а обобщённые типы вроде List<Handler<Order>> Spring различает по параметру типа.
Где спотыкаются
Думают, что @Primary влияет на коллекцию. Он решает конфликт только при внедрении одного бина, в List попадут все реализации.
Не знают, что будет, если реализаций нет. Обязательная инъекция коллекции падает при старте с NoSuchBeanDefinitionException, спасают ObjectProvider или @Autowired(required = false).
Внедряют prototype-бины в List синглтона и ждут новый экземпляр на каждый вызов. Коллекция собирается один раз при создании синглтона, дальше это те же объекты.