Стереотипы
@Component помечает класс как бин — Spring находит его через component-scan и сам инстанцирует. @Service, @Repository, @Controller/@RestController — специализации @Component: технически тот же эффект, но семантически обозначают слой.
У @Repository есть и реальное поведение, а не только семантика: он включает exception translation — перевод низкоуровневых исключений JDBC/JPA в единую иерархию Spring DataAccessException (unchecked), чтобы код доступа к данным не зависел от конкретной технологии.
@Bean против @Component
@Component (и специализации) — для СВОИХ классов, которые можно пометить аннотацией. @Bean-метод в @Configuration — для ЧУЖИХ/библиотечных классов, которые пометить нельзя: вы сами создаёте объект и отдаёте контейнеру.
Так конфигурация остаётся явной: свой код сканируется, внешние объекты регистрируются руками (и помните про full mode @Configuration из урока про контекст).
@Configuration
class AppConfig {
@Bean ObjectMapper objectMapper() { return new ObjectMapper(); } // сторонний класс
}
Component scan
Чтобы стереотипы нашлись, нужен component-scan. В Spring Boot он включён через @SpringBootApplication, который сканирует пакет главного класса и все вложенные — поэтому компоненты обычно держат в том же или нижележащем пакете.
Область и правила настраивают @ComponentScan (basePackages, include/excludeFilters). Частая ошибка новичка — положить бин вне сканируемого пакета и удивляться, что его «нет».
Автосвязывание @Autowired
Внедрение по умолчанию идёт by type: контейнер ищет бин подходящего типа. Если кандидат один — всё просто; на конструкторе с одним вариантом @Autowired даже не нужен.
Если по типу подходящих несколько, Spring пытается разрешить by name (по имени поля/параметра). Если и это не помогает — ошибка NoUniqueBeanDefinitionException на старте.
Разрешение неоднозначности
Когда бинов одного типа несколько, выбор уточняют: @Primary помечает кандидата по умолчанию, а @Qualifier("name") в точке инъекции выбирает конкретного. Можно внедрить и ВСЕ бины типа сразу — как List<Handler> или Map<String, Handler> (имя бина → бин), что удобно для паттерна «стратегия/реестр».
Существуют и стандартные аналоги: @Resource (JSR-250, by name) и @Inject (JSR-330, как @Autowired) — но в Spring-проектах обычно используют @Autowired + @Qualifier.
@Service
class Dispatcher {
private final Map<String, Handler> handlers; // имя бина -> Handler, все реализации
Dispatcher(Map<String, Handler> handlers) { this.handlers = handlers; }
}
Как отвечать на собеседовании
Назовите стереотипы и подчеркните, что @Repository не просто семантика, а exception translation в DataAccessException. Различите @Component (свой класс, скан) и @Bean (чужой класс, @Configuration). Объясните автосвязывание (by type → by name) и разрешение конфликтов (@Primary/@Qualifier, а также инъекцию List/Map всех бинов типа). Упомяните типичную ошибку с пакетом вне component-scan.