На каких этапах инициализации контекста можно избавиться от ненужного бина в Spring
Что проверяют
Понимаете ли вы, что определение бина и сам бин это разные вещи, и знаете ли точку, после которой убрать бин уже нельзя. Заодно смотрят, отличаете ли вы возможности ядра Spring от того, что добавляет Boot.
Как отвечать
Идите по порядку жизни контекста:
- чтение определений: сканирование пакетов,
@Import, авто-конфигурации Boot; - обработка определений:
BeanFactoryPostProcessorиBeanDefinitionRegistryPostProcessor, последний момент, когда определение можно снять с регистрации; - создание синглтонов и внедрение зависимостей;
BeanPostProcessor,@PostConstruct, готовый контекст.
Отсюда и рычаги. До регистрации: excludeFilters у @ComponentScan, исключение авто-конфигурации через spring.autoconfigure.exclude. На уровне определений: @Profile, @Conditional и его производные из Boot вроде @ConditionalOnProperty и @ConditionalOnMissingBean, тут бин не отключается, он просто не регистрируется. Программно:
@Bean
static BeanFactoryPostProcessor dropLegacy() {
return factory -> ((BeanDefinitionRegistry) factory)
.removeBeanDefinition("legacyClient");
}Метод обязан быть static, иначе конфигурация поднимется слишком рано и обработка не отработает.
Где спотыкаются
Называют @Lazy способом избавиться от бина. Он только откладывает создание: определение остаётся, первая же инъекция поднимет бин, а поломанная конфигурация всплывёт не на старте, а под нагрузкой.
Путают BeanFactoryPostProcessor и BeanPostProcessor. Первый правит определения до создания, второй получает уже готовый экземпляр, и удалять оттуда нечего.
Думают, что условия пересчитываются на живом контексте. @Conditional и @Profile оцениваются один раз при регистрации, поменять профиль на лету нельзя, нужен перезапуск приложения.