Что хранит ApplicationContext в Spring
Что проверяют
Понимаете ли вы, что происходит внутри контейнера, а не только умеете ставить @Autowired. Ждут, что вы отличите определения бинов от готовых объектов и объясните разницу с BeanFactory. Следом часто спрашивают про жизненный цикл бина или циклические зависимости.
Как отвечать
ApplicationContext расширяет BeanFactory и добавляет к нему ещё несколько интерфейсов. Внутри он держит:
- определения бинов:
BeanDefinitionс классом, скоупом, зависимостями, методами инициализации и уничтожения. ВDefaultListableBeanFactoryэто картаbeanDefinitionMap; - кэш синглтонов: готовые экземпляры в
DefaultSingletonBeanRegistry. Рядом ещё два уровня кэша для ранних ссылок, через них Spring разрешает циклы при внедрении через поля и сеттеры; Environment: активные профили иPropertySourceизapplication.yml, переменных окружения, аргументов запуска;- постпроцессоры:
BeanPostProcessorиBeanFactoryPostProcessor, на них держатся@Autowired, прокси для@Transactional,@ConfigurationProperties; - события:
ApplicationEventPublisherи слушатели@EventListener; - сообщения и ресурсы:
MessageSourceдля локализации иResourceLoaderдля путейclasspath:и файлов; - родительский контекст, если он есть.
Важная оговорка: prototype бины контекст создаёт, но не хранит и не вызывает у них методы уничтожения.
Отличие от голой BeanFactory: контекст при refresh() сразу создаёт все синглтоны, кроме @Lazy, сам регистрирует постпроцессоры и публикует события. В Spring Boot реализацию выбирает SpringApplication, для сервлетного приложения это AnnotationConfigServletWebServerApplicationContext.
Где спотыкаются
Говорят, что контекст хранит все бины, включая prototype. Отсюда ожидание, что @PreDestroy у prototype сработает при закрытии приложения.
Путают определения и экземпляры. На этапе BeanFactoryPostProcessor объектов ещё нет, есть только метаданные, и менять можно именно их.
Советуют доставать зависимости через context.getBean() в бизнес-коде. Это service locator: он прячет зависимости и мешает тестам. Нормальный путь это внедрение через конструктор.