← 每日面试题 学习看板

如何根据配置动态生成Spring的Bean?

面试题/00java/04 框架/01Spring/03依赖注入与配置/如何根据配置动态生成Spring的Bean?.md

面试记录 2026-10-27(Round 29)

题目:如何根据配置动态生成 Spring 的 Bean?

难度:difficulty/medium

评分:⭐⭐⭐☆☆(3/5)

我的回答

根据配置动态生成 spring bean 主要有两种:启动阶段批量配置 BeanDefinitionRegistryPostProcessor 来创建;通过 FactoryBean 创建单个的类。

点评

优点:方向对——BDRegistryPostProcessor 批量 + FactoryBean 单个。

不足:过于简略,漏 @Bean+@Configuration、ImportBeanDefinitionRegistrar、ConditionalOnXxx、BeanDefinitionBuilder。

补充:核心场景是"按配置决定是否注册 / 批量注册"。


完整讲解(权威版)

最后更新:2026-10-27 · 基于第 1 次作答

L1 · 30 秒速记

结论:动态生成 Bean 的本质是在 BeanDefinition 阶段注册元数据,核心接口是 BeanDefinitionRegistryPostProcessor。 关键词:BeanDefinition 先行 · BDRegistryPostProcessor · ImportBeanDefinitionRegistrar 边界:注册必须发生在实例化之前(容器刷新早期)。

L2 · 核心讲解

核心考点定位:考察 Bean 生命周期早期 + 注册机制。面试官想排除"动态生成 = 直接 new 对象丢给容器"的错误认知。

机制链(≥3 环):

  1. 容器刷新 → 调用 BeanDefinitionRegistryPostProcessor:为什么——这是容器早期扩展点,此时 BeanDefinition 还没实例化
  2. 遍历配置 → BeanDefinitionBuilder 构建定义:为什么——用 builder 构建元数据,而非 new 对象
  3. registerBeanDefinition → 注册进容器:为什么——注册定义后,容器后续统一实例化、依赖注入、管理生命周期

证据锚点(≥10):

对比与权衡:

方式正确性粒度失败模式适用边界
BDRegistryPostProcessor高批量注册时机早按配置批量注册
ImportBeanDefinitionRegistrar高模块依赖 @Import模块化引入
FactoryBean高单点定制复杂第三方类封装
@ConditionalOnXxx中单点条件误配开关式组件

常见误区:

  1. 错误:动态生成 = new 对象放入容器 → 正确:注册 BeanDefinition,容器统一实例化 → 为什么:直接 new 绕过生命周期,依赖注入失效
  2. 错误:BDRegistryPostProcessor 和 BeanFactoryPostProcessor 一样 → 正确:前者能新增定义,后者只能改属性 → 为什么:Registry 是注册器,PostProcessor 是修改器
  3. 错误:任意时机都能注册 → 正确:必须容器刷新早期 → 为什么:实例化后注册不进去
  4. 错误:用反射直接 new 多个 → 正确:用 BeanDefinitionBuilder 构建 → 为什么:builder 支持设置属性/scope,new 做不到

适用边界:动态注册只适合"启动时已知"的 Bean;运行时动态增减 Bean 不是主流,用 @Lazy/工厂更合适。

延伸追问(≥3)

  1. BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 区别?
  1. @Import 和 @ComponentScan 区别?
  1. 动态注册的 Bean 如何注入?

面试者参考回答(400–700 字)

【结论】 面试官您好,动态生成 Bean 的本质是在 BeanDefinition 阶段注册元数据,核心接口是 BeanDefinitionRegistryPostProcessor。

【三点】 第一,Spring 先注册 BeanDefinition 再实例化,所以"动态生成"就是提前注册定义,不是直接 new 对象。第二,最常用 BeanDefinitionRegistryPostProcessor——在容器刷新早期遍历配置,用 BeanDefinitionBuilder 构建并 registerBeanDefinition,可批量注册。第三,单点定制用 FactoryBean,按条件生成用 @ConditionalOnXxx / @Profile,模块化引入用 ImportBeanDefinitionRegistrar。

【边界】 当然,动态注册必须发生在实例化之前(容器刷新早期),晚了注册不进去;且批量注册要用 BeanDefinitionBuilder 而不是直接 new。


作答历史

#日期评分本轮主要问题记录
12026-10-273/5过简,漏 @Bean/@ConditionalOnXxx第 1 次