Spring的BeanFactory和FactoryBean有 什么不同
BeanFactory
概述
BeanFactory
是Spring IoC容器的基础接口,提供了基本的bean管理功能。它允许你以编程方式管理和创建bean实例,并支持依赖注入。
主要功能
- 延迟加载:
BeanFactory
采用延迟加载机制,只有当你调用getBean()
方法时,才会真正创建并返回一个bean实例。 - 依赖注入:通过构造器注入、setter方法注入等方式,
BeanFactory
可以自动解决并注入依赖关系。 - 生命周期管理:支持bean的初始化前和销毁后的回调方法(如
@PostConstruct
和@PreDestroy
注解)。
核心方法
T getBean(String name)
:根据名称获取bean实例。T getBean(Class<T> requiredType)
:根据类型获取bean实例。Object getBean(String name, Object... args)
:根据名称和构造参数获取bean实例。boolean containsBean(String name)
:检查是否包含指定名称的bean。void destroySingletons()
:销毁所有单例bean。
使用场景
尽管BeanFactory
是Spring容器的基础接口,但在大多数情况下,开发者会使用其扩展接口ApplicationContext
,因为它提供了更多高级特性,如国际化消息、事件传播、AOP集成等。
FactoryBean
概述
FactoryBean
是一个特殊的工厂模式接口,用于自定义bean的创建逻辑。当某些bean的创建过程非常复杂或需要特殊处理时,可以通过实现FactoryBean
接口来封装这些复杂的创建逻辑。
接口定义
FactoryBean
接口包含三个核心方法:
T getObject()
:返回由工厂创建的对象实例。Class<?> getObjectType()
:返回由工厂创建的对象类型。如果提前无法确定类型,则可以返回null
。boolean isSingleton()
:指示由该工厂创建的对象是否为单例。如果是单例,Spring容器将只调用一次getObject()
方法,并缓存结果;否则,每次请求该bean时都会调用getObject()
方法。
使用示例
假设我们有一个需要复杂初始化过程的类MyComplexBean
,我们可以使用FactoryBean
来简化其创建过程:
public class MyComplexBean {
private String property;
public MyComplexBean(String property) {
this.property = property;
}
// Getters and setters
}
public class MyComplexBeanFactory implements FactoryBean<MyComplexBean> {
private String initValue;
public void setInitValue(String initValue) {
this.initValue = initValue;
}
@Override
public MyComplexBean getObject() throws Exception {
// 复杂的初始化逻辑
return new MyComplexBean(initValue);
}
@Override
public Class<?> getObjectType() {
return MyComplexBean.class;
}
@Override
public boolean isSingleton() {
return true; // 指定是否为单例
}
}
配置方式
- XML配置:
<bean id="myComplexBean" class="com.example.MyComplexBeanFactory">
<property name="initValue" value="initialized value"/>
</bean>
- Java配置:
@Configuration
public class AppConfig {
@Bean
public MyComplexBeanFactory myComplexBeanFactory() {
MyComplexBeanFactory factory = new MyComplexBeanFactory();
factory.setInitValue("initialized value");
return factory;
}
}
关系与交互
角色差异
BeanFactory
:作为Spring IoC容器的基础接口,负责管理所有bean的生命周期和配置。它是整个IoC容器的核心,提供了基础的bean管理和依赖注入功能。FactoryBean
:是一种特殊的bean类型,用于定制化bean的创建过程。它可以封装复杂的初始化逻辑,使得一些难以直接实例化的对象能够被Spring容器管理。
如何交互
- 当你在Spring容器中注册了一个实现了
FactoryBean
接口的bean时,比如上面例子中的MyComplexBeanFactory
,当你调用BeanFactory.getBean("myComplexBean")
时,实际上会得到的是FactoryBean.getObject()
返回的对象,而不是FactoryBean
本身。 - 如果你想获取
FactoryBean
本身的实例,你需要使用&
前缀,即BeanFactory.getBean("&myComplexBean")
。
应用场景
- 使用
FactoryBean
的典型场景:- 当bean的创建过程非常复杂(例如需要访问外部资源、执行复杂的初始化逻辑)时,可以通过实现
FactoryBean
接口来自定义bean的创建过程。 - 对于那些需要代理的对象(如动态代理)、连接池对象或其他需要特殊处理的对象,也可以使用
FactoryBean
来简化其创建过程。
- 当bean的创建过程非常复杂(例如需要访问外部资源、执行复杂的初始化逻辑)时,可以通过实现
实际应用案例
假设我们需要一个数据库连接池对象,并且希望这个对象能够在Spring容器中被管理。我们可以使用FactoryBean
来实现这一点:
import org.apache.commons.dbcp2.BasicDataSource;
public class DataSourceFactory implements FactoryBean<BasicDataSource> {
private String url;
private String username;
private String password;
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public BasicDataSource getObject() throws Exception {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setInitialSize(5); // 初始化连接数量
dataSource.setMaxTotal(10); // 最大连接数
return dataSource;
}
@Override
public Class<?> getObjectType() {
return BasicDataSource.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
在Spring配置文件中注册这个FactoryBean
:
<bean id="dataSource" class="com.example.DataSourceFactory">
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
或者使用Java配置:
@Configuration
public class AppConfig {
@Bean
public DataSourceFactory dataSourceFactory() {
DataSourceFactory factory = new DataSourceFactory();
factory.setUrl("jdbc:mysql://localhost:3306/mydb");
factory.setUsername("root");
factory.setPassword("password");
return factory;
}
}
这样,当我们调用context.getBean("dataSource")
时,Spring容器将返回一个已经配置好的BasicDataSource
实例。
总结
BeanFactory
是Spring IoC容器的基础接口,提供基本的bean管理功能。它是一个简单的IoC容器,适用于需要细粒度控制bean创建过程的场景。FactoryBean
是一种特殊的bean类型,用于定制化bean的创建过程。它特别适用于那些需要复杂初始化逻辑的bean,如代理对象、连接池对象等。- 两者结合使用,可以为Spring应用提供强大的灵活性和可扩展性,使得即使是复杂的bean也能被高效地管理和创建。通过这种方式,开发者可以更好地控制bean的创建过程,并充分利用Spring容器的功能。