这是一个由在{@link BeanFactory}中使用的对象所实现的接口,它们本身就是用于创建个别对象的工厂。当一个bean实现了这个接口时,它表明它不是一个直接暴露的常规bean实例,而是用于创建和暴露另一个对象的工厂。
实现了这个接口的bean不能被作为普通的bean使用。FactoryBean在定义时遵循了bean的形式,但是对于 bean 引用 (通过调用 getObject()
),始终暴露的是由 FactoryBean 创建的对象本身。
FactoryBean可以支持单例和原型两种作用域,同时可以按需延迟创建对象或在启动时立即创建。通过实现{@link SmartFactoryBean}接口,还可以提供更精细的行为元数据信息。
该接口在Spring框架内部被广泛使用,例如在AOP中的{@link org.springframework.aop.framework.ProxyFactoryBean}或{@link org.springframework.jndi.JndiObjectFactoryBean}中。它也可以用于自定义组件,但这通常更适用于基础架构代码。
在Spring框架的核心功能中,FactoryBean被用于以下目的:
- 使用代理模式创建AOP代理对象:AOP代理的创建依赖于
ProxyFactoryBean
,通过实现FactoryBean来封装代理对象的创建逻辑。 - 与JNDI整合:Spring使得与Java命名和目录接口(JNDI)进行集成的过程更加简化。
JndiObjectFactoryBean
作为一个FactoryBean被使用,它能够管理JNDI对象的查找和暴露。 - 集成其他基础设施相关组件:比如与缓存、事务管理或消息队列等相关的组件,为了更好地集成和适配,可能会自定义FactoryBean。
FactoryBean是一个以编程方式定义的契约(contract)。实现类不应依赖于注解驱动的注入或其他反射机制。在引导过程中,对 getObjectType()
和 getObject()
方法的调用可能会比任何后处理器的设置更早进行。如果你需要访问其他的bean,请实现 BeanFactoryAware
接口并以编程方式获取它们。
容器只负责管理FactoryBean实例的生命周期,而不负责管理FactoryBean创建的对象的生命周期。因此,容器不会自动调用暴露的bean对象上的销毁方法(例如 java.io.Closeable#close()
)。相反,FactoryBean应该实现 DisposableBean
接口,并将任何关闭的调用委托给底层对象。
FactoryBean对象参与包含的BeanFactory的bean创建同步。通常除了FactoryBean本身(或类似情况)需要进行懒初始化之外,通常不需要进行内部同步。
public interface FactoryBean<T> {}
这是一个属性的名称,可以在 org.springframework.beans.factory.config.BeanDefinition
上通过 org.springframework.core.AttributeAccessor#setAttribute
方法设置。当无法从工厂Bean类中推断出对象类型时,工厂Bean可以使用该属性来表明其对象类型。
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
该方法返回由此工厂管理的对象的实例(可能是共享的或独立的)。与`BeanFactory`类似,这允许支持单例和原型的设计模式。如果在调用时该FactoryBean尚未完全初始化(例如因为它涉及循环引用),则抛出相应的`FactoryBeanNotInitializedException`异常。从Spring 2.0版本开始,FactoryBean被允许返回`null`对象。在这种情况下,容器将会将其视为正常值使用,不再抛出`FactoryBeanNotInitializedException`异常。现在鼓励FactoryBean实现根据需要自行抛出`FactoryBeanNotInitializedException`。
@Nullable
T getObject() throws Exception;
返回此FactoryBean创建的对象的类型,如果提前无法确定,则返回null。这使得我们可以在不实例化对象的情况下检查特定类型的bean,例如在自动装配中。对于创建单例对象的实现,应尽量避免创建单例;而是预先估计对象的类型。对于原型对象,在这里返回一个有意义的类型也是可取的。此方法可以在此FactoryBean完全初始化之前调用。它不应依赖于初始化期间创建的状态;当然,如果存在这样的状态,仍然可以使用它。
注意: 自动装配会忽略返回null的FactoryBean。因此,强烈建议正确实现此方法,使用当前FactoryBean的状态。
@Nullable
Class<?> getObjectType();
如果FactoryBean表明它持有一个单例对象,那么从 getObject()
方法返回的对象可能会被所属的BeanFactory缓存。因此,除非FactoryBean始终公开相同的引用,否则不应返回true。
FactoryBean本身的单例状态通常由所属的BeanFactory提供;通常,它必须在那里定义为单例。
注意:此方法返回false并不必然意味着返回的对象是独立的实例。扩展了SmartFactoryBean接口的实现可以通过其SmartFactoryBean#isPrototype()方法显式地指示独立实例。如果FactoryBean的isSingleton()方法返回false,并且它没有实现此扩展接口的话,则普通的FactoryBean实现被默认假设为总是返回独立的实例。
默认实现返回true,因为FactoryBean通常管理单例实例。
default boolean isSingleton() {
return true;
}