Где Spring ищет кандидатов в бины
Что проверяют
Знаете ли вы механику компонентного сканирования, а не только набор аннотаций. Типичный уточняющий вопрос: почему Spring Boot не видит ваш сервис, лежащий в соседнем пакете, и как это исправить.
Как отвечать
Кандидатов в бины Spring ищет в classpath, в пакетах, указанных для сканирования:
- область поиска:
@ComponentScanзадаёт базовые пакеты черезbasePackagesилиbasePackageClasses. Если их не указать, сканируется пакет класса с аннотацией и все подпакеты. В Spring Boot@SpringBootApplicationуже включает@ComponentScan, поэтому граница поиска это пакет главного класса; - кто выполняет:
ClassPathBeanDefinitionScannerна основеClassPathScanningCandidateComponentProvider. Он читает метаданные классов через ASM, не загружая сами классы, и прогоняет их через фильтры; - что считается кандидатом: по умолчанию класс с
@Componentили с аннотацией, для которой она мета-аннотация:@Service,@Repository,@Controller,@RestController,@Configuration. Класс должен быть конкретным и самостоятельным, интерфейс или абстрактный класс без методов@Lookupкандидатом не станет; - фильтры:
includeFilters,excludeFiltersиuseDefaultFilters = falseменяют правила отбора.
Затем назовите источники определений бинов помимо сканирования: методы @Bean в конфигурационных классах, @Import, XML и автоконфигурации Spring Boot. Автоконфигурации не сканируются, а перечисляются в файле META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports и включаются условиями @ConditionalOn....
Где спотыкаются
Называют @Autowired способом поиска бинов. Это внедрение зависимостей в уже найденные бины, на поиск кандидатов оно не влияет.
Кладут класс вне пакета главного класса Spring Boot и получают NoSuchBeanDefinitionException. Нужно перенести класс, расширить сканирование или подключить конфигурацию через @Import.
Путают поиск кандидатов с их регистрацией. @Profile и @Conditional не ищут классы, а отсекают уже найденные определения, если условие не выполнено.