Spring FactoryBean 核心机制

Spring FactoryBean 核心机制

一、核心概念区分

在理解 FactoryBean 时,需先明确两个关键对象的区别,避免混淆:

对象类型 定义 默认特性
FactoryBean 自身 实现 FactoryBean<T> 接口的“工厂 bean”,负责生产目标 bean 作用域默认是 singleton(容器启动时初始化自身实例,仅一次)
FactoryBean 生产的目标 bean 由 FactoryBean 的 getObject() 方法返回的最终业务对象(如 MyBean 作用域由 isSingleton() 控制,默认返回 true(即单例)

二、getObject() 方法执行时机

getObject() 是 FactoryBean 生产目标 bean 的核心方法,其执行时机分「默认场景」和「特殊场景」,核心取决于目标 bean 的获取方式和作用域。

1. 默认场景(目标 bean 为单例,isSingleton()=true

这是最常见的场景,getObject() 遵循「按需执行」原则,不会在容器启动时立即执行,而是延迟到「首次需要目标 bean 时」触发,具体分两种触发方式:

(1)通过 getBean() 主动获取目标 bean 时

  • 容器启动阶段:仅初始化 FactoryBean 自身实例,不调用 getObject()
  • 首次调用 context.getBean(目标bean类型/名称) 时:触发 getObject() 生成目标 bean,生成后存入容器缓存。
  • 后续调用 getBean():直接从缓存获取目标 bean,不再执行 getObject()

示例代码流程

// 1. 容器启动:仅初始化 MyFactoryBean 实例,不打印日志
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

// 2. 首次 getBean:触发 getObject(),打印"getObject() 被调用"
MyBean bean1 = context.getBean(MyBean.class);

// 3. 后续 getBean:直接用缓存,不打印日志
MyBean bean2 = context.getBean(MyBean.class);

(2)通过 @Autowired 注入目标 bean 时

getObject() 的执行时机取决于「被注入类的初始化时机」:

  • 若被注入类(如 ServiceA)是单例(默认):容器启动时初始化 ServiceA,执行依赖注入时触发 getObject() 生成目标 bean,注入后缓存目标 bean。
  • 若被注入类是 prototype:每次创建 ServiceA 实例时,执行依赖注入才触发 getObject()(若目标 bean 也是 prototype,则每次都生成新实例)。

示例代码流程

// 被注入类(单例)
@Component
public class ServiceA {
    // 注入 FactoryBean 生产的 MyBean
    @Autowired
    private MyBean myBean; 
}

// 容器启动时:
// 1. 初始化 MyFactoryBean(自身)
// 2. 初始化 ServiceA,执行依赖注入
// 3. 触发 MyFactoryBean 的 getObject() 生成 MyBean,注入到 ServiceA

2. 特殊场景(目标 bean 为原型,isSingleton()=false

若重写 isSingleton() 并返回 false,目标 bean 为原型作用域:

  • 无论通过 getBean() 还是 @Autowired每次获取/注入目标 bean 时,都会执行一次 getObject(),生成新的目标 bean 实例,不缓存。

三、关键对比:普通 Bean vs FactoryBean 生产的 Bean

当两种方式都生成同一个类型的 Bean(如 BeanA)时,核心区别在于「Bean 的创建时机」:

对比维度 普通 Bean(直接定义,如 @Component/@Bean FactoryBean 生产的 Bean
创建时机 容器启动阶段(单例默认预初始化),早于依赖注入 延迟到首次获取/注入时(getObject() 执行时)
核心逻辑 直接由 Spring 容器实例化、初始化 由 FactoryBean 的 getObject() 自定义创建逻辑(支持复杂对象)
适用场景 简单对象(无复杂创建逻辑) 复杂对象(如依赖多步骤构建、第三方组件集成等)

四、核心结论

  1. FactoryBean 自身默认是单例,容器启动时初始化,但不立即生成目标 bean。
  2. 默认场景(目标 bean 单例)下,getObject() 延迟执行,触发时机是「首次获取/注入目标 bean 时」。
  3. 普通 Bean 比 FactoryBean 生产的 Bean 更早创建(容器启动阶段 vs 首次使用时)。
  4. 目标 bean 的作用域由 isSingleton() 控制,决定 getObject() 是执行一次(单例)还是多次(原型)。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容