Может ли любой класс быть Spring Bean
Что проверяют
Различаете ли вы «быть бином» и «попасть в сканирование компонентов», и знаете ли, где на самом деле появляются ограничения. Следом обычно спрашивают про final класс с @Transactional или про Kotlin.
Как отвечать
Бин это любой объект, жизненным циклом которого управляет контейнер. Поэтому ответ: практически любой класс, вопрос только в способе регистрации.
@Beanв@Configuration: метод возвращает что угодно, включая сторонние иfinalклассы, на которые не повесить аннотацию:ObjectMapper,Clock, HTTP-клиент;- сканирование через
@Component: здесь требования уже есть. Класс должен быть конкретным, верхнего уровня илиstaticвложенным, абстрактные классы и интерфейсы сканер пропускает; - программная регистрация:
GenericApplicationContext.registerBean()илиBeanDefinitionRegistryPostProcessor, если набор бинов известен только в рантайме.
Конструктор по умолчанию не нужен: с версии 4.3 единственный конструктор используется для внедрения без @Autowired. Подойдёт даже приватный, контейнер вызовет его через рефлексию.
Реальные ограничения появляются, когда бину нужен прокси. @Transactional, @Cacheable, @Async и аспекты работают через обёртку, и Spring Boot по умолчанию строит её как CGLIB-подкласс. final класс унаследовать нельзя, поэтому контекст не поднимется. С final методами хуже: ошибки нет, аннотация на них просто молча не работает. В Kotlin классы по умолчанию final, поэтому подключают плагин kotlin-spring, который открывает классы с аннотациями Spring.
Ещё нюанс: нестатический внутренний класс без экземпляра внешнего контейнер не создаст.
Где спотыкаются
Утверждают, что final класс не может быть бином. Может, через @Bean, проблема только с проксированием.
Говорят, что обязательны аннотация и пустой конструктор. Оба требования неверны, и интервьюер это заметит.
Не знают про вызов метода изнутри того же бина: this.save() идёт мимо прокси, и @Transactional на save() не срабатывает. Этот вопрос почти всегда следует за темой прокси.