BeanFactory против ApplicationContext
BeanFactory — базовый контейнер с ленивым созданием бинов по запросу. ApplicationContext — его надстройка, которую и используют на практике: он жадно создаёт синглтоны на старте (ошибки конфигурации видны сразу — fail-fast), публикует события (ApplicationEvent), поддерживает i18n, автоматически находит BeanPostProcessor/BeanFactoryPostProcessor и интегрируется с AOP.
Практически всегда работают с ApplicationContext; BeanFactory — это его «ядро» для понимания.
Способы конфигурации
Бины объявляют тремя путями: Java-config (@Configuration + методы @Bean), аннотации + component-scan (@Component на классе) и XML (легаси). Современный стандарт — Java-config плюс сканирование компонентов; XML встречается в старых проектах.
Свой класс помечают @Component/@Bean-стереотипом, чужой/библиотечный регистрируют через @Bean-метод (подробнее — в уроке про стереотипы).
@Configuration: full против lite
Класс с @Configuration Spring проксирует через CGLIB (full mode). Зачем: если один @Bean-метод вызывает другой @Bean-метод, прокси перехватывает вызов и возвращает тот же singleton из контейнера, а не создаёт новый объект.
Если же поставить @Bean в обычном классе без @Configuration (lite mode), такого проксирования нет — прямой вызов @Bean-метода создаст НОВЫЙ объект мимо контейнера. Это классический источник тонких багов с «двумя экземплярами синглтона».
@Configuration
class AppConfig {
@Bean DataSource ds() { return new HikariDataSource(); }
@Bean OrderRepo repo() { return new OrderRepo(ds()); } // ds() вернёт тот же singleton (full mode)
}
Профили и Environment
@Profile("dev") делает бин/конфигурацию активными только в указанном профиле (spring.profiles.active=dev) — так разводят dev/test/prod-инфраструктуру. Environment абстрагирует источники свойств (переменные окружения, application.yml, аргументы запуска) с приоритетами.
Свойства внедряют через @Value("${...}") (точечно) или, что предпочтительнее, через типобезопасные @ConfigurationProperties-классы (группа свойств с валидацией).
@Conditional и BeanFactoryPostProcessor
@Conditional регистрирует бин только при выполнении условия. На его основе построены @ConditionalOnProperty/OnMissingBean/OnClass — фундамент Boot-автоконфигурации (отдельный урок): «создайте бин, только если его ещё нет / есть нужный класс / включено свойство».
BeanFactoryPostProcessor (BFPP), в отличие от BeanPostProcessor, работает раньше — над BeanDefinition'ами до создания бинов (пример — подстановка плейсхолдеров свойств). Порядок «BFPP правит определения → бины создаются → BPP правят объекты» полезно держать в голове.
Как отвечать на собеседовании
Противопоставьте BeanFactory (ленивый) и ApplicationContext (жадные синглтоны/события/fail-fast). Объясните full vs lite @Configuration (CGLIB-прокси → межбиновые вызовы дают тот же singleton; в lite — новый объект). Назовите профили и @ConfigurationProperties, и различите BFPP (над определениями) и BPP (над объектами), с @Conditional как мостом к автоконфигурации.