BeanFactory
和 FactoryBean
都是 Spring 框架中的核心接口,且有着不同的目的和应用场景。我们可以从源码角度分析它们的区别,并探讨它们的作用和应用场景。
1. BeanFactory
BeanFactory
是 Spring 中最基本的容器接口之一。它定义了 Spring 容器的基本操作方法,比如获取 Bean 对象、初始化 Bean 等。
关键方法
java
public interface BeanFactory { Object getBean(String name) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; }
功能:
BeanFactory
负责根据 Bean 的名称和配置来获取 Bean 实例。- 它通过
getBean()
方法来从容器中获取 Bean。 - 它不负责实例化单例 Bean 直到调用
getBean()
时才实例化,所以它是懒加载的(Lazy Initialization)。
适用场景:
- 在大多数情况下,我们通常使用
ApplicationContext
来代替BeanFactory
,因为ApplicationContext
是BeanFactory
的子接口,并且提供了更多的功能(如国际化、事件传播、AOP 等)。 - 如果你的应用非常轻量,且只需要基础的 Bean 管理功能,可以使用
BeanFactory
。
2. FactoryBean
FactoryBean
是 Spring 中的一个接口,它允许开发者控制 Bean 的实例化过程。通过实现 FactoryBean
接口,开发者可以自定义 Bean 的创建逻辑。
关键方法
java
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }
功能:
getObject()
:返回一个新的或现有的对象。通过FactoryBean
,你可以创建复杂的 Bean 实例,或者返回非标准的对象类型。getObjectType()
:返回该FactoryBean
创建的对象的类型。isSingleton()
:如果这个FactoryBean
创建的对象是单例的,则返回true
;否则返回false
。
适用场景:
- 当你需要自定义 Bean 的创建逻辑时,使用
FactoryBean
是一个非常好的选择。典型的场景包括:- 工厂模式:需要动态地创建不同类型的 Bean。
- 第三方库的适配 :当你需要将第三方库中的某些对象集成到 Spring 容器中时,可以通过
FactoryBean
来封装其创建过程。 - 动态代理 :如果需要在 Spring 容器中管理动态代理对象,可以通过
FactoryBean
进行创建。
3. BeanFactory 与 FactoryBean 的区别
特性 | BeanFactory |
FactoryBean |
---|---|---|
目的 | 管理 Spring 容器中的所有 Bean | 自定义 Bean 的创建过程 |
主要功能 | 获取 Bean、管理 Bean 生命周期 | 创建特定的 Bean 实例,控制 Bean 的初始化逻辑 |
实现方式 | 通过 getBean() 获取 Bean |
通过 getObject() 创建 Bean,通常与工厂模式结合使用 |
使用场景 | 基本的 Bean 管理与获取 | 需要自定义 Bean 创建过程时,或者动态 Bean 的情况 |
是否懒加载 | 默认是懒加载(对于单例 Bean) | 根据 isSingleton() 的实现来决定 Bean 的生命周期 |
4. Spring 中的应用场景
4.1 BeanFactory 的应用
BeanFactory
一般在 Spring 中并不直接使用,开发者更多的是使用 ApplicationContext
。但是,在一些内存或性能特别敏感的应用场景下,BeanFactory
仍然有它的价值。例如,当你只需要非常简单的 Bean 获取功能时,可以通过 BeanFactory
实现更加轻量的容器。
4.2 FactoryBean 的应用
- 动态代理对象 :
FactoryBean
可以用来创建动态代理。例如,Spring AOP 会使用FactoryBean
来创建代理对象。 - 第三方库集成 :某些第三方库的对象可能无法直接作为 Spring Bean 创建。这时可以通过
FactoryBean
来封装这些对象的创建过程,使它们能够被 Spring 容器管理。 - 复杂 Bean 初始化 :当 Bean 的初始化过程复杂,需要多步处理时,可以使用
FactoryBean
来处理 Bean 的实例化。
示例:FactoryBean 的使用
java
public class MyBeanFactory implements FactoryBean<MyBean> {
@Override
public MyBean getObject() throws Exception {
return new MyBean(); // 这里是自定义的创建逻辑
}
@Override
public Class<?> getObjectType() {
return MyBean.class;
}
@Override
public boolean isSingleton() {
return true; // 如果需要单例,返回 true
}
}
在配置文件中,使用 FactoryBean
创建 MyBean
:
<bean id="myBean" class="com.example.MyBeanFactory"/>
总结:
BeanFactory
是 Spring 中最基础的容器接口,负责获取和管理 Bean。FactoryBean
是一个工厂接口,允许你自定义 Bean 的创建逻辑,并将其交给 Spring 管理。- 使用
BeanFactory
时你只能获取已经存在的 Bean,而使用FactoryBean
时可以控制 Bean 的创建过程,适用于复杂的初始化或自定义实例化的场景。
通过理解这两个接口的区别,可以帮助开发者在合适的场景下选择合适的接口和方式来管理 Bean 的生命周期和创建。
实际应用场景
BeanFactory
<T> T getBean(String var1, Class<T> var2) throws BeansException;
java
String statuseServiceBeanname = STATE_SERVICE_PRE + stateMachineType;
IStatusService iStatusService = abstractStateMachineEngine.getApplicationContext().getBean(statuseServiceBeanname, IStatusService.class);
FactoryBean - getObject
java
@Bean(name = "mallSqlSessionFactory")
public SqlSessionFactory mallSqlSessionFactory(@Qualifier("mallDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
Interceptor[] plugins = new Interceptor[]{new PageHelper()};
bean.setPlugins(plugins);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mappers/*.xml"));
return bean.getObject();
}