Spring BeanFactory 和 FactoryBean 详解
一、基本概念对比
BeanFactory
BeanFactory 是 Spring IoC 容器的顶层接口,代表着 Spring 的核心概念------IoC(控制反转)容器。它定义了管理 Bean 的最基本规范和功能。
- 本质:一个工厂接口,负责生产和管理 Spring 容器中的所有 Bean
- 职责:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖关系
- 设计目的:提供 IoC 容器的基本功能规范
FactoryBean
FactoryBean 是一个特殊的 Bean,它实现了 org.springframework.beans.factory.FactoryBean<T>
接口,用于创建复杂的 Bean 实例。
- 本质:一个能生产或修饰其他对象生成的工厂 Bean
- 职责:定制实例化 Bean 的逻辑,封装复杂对象的创建过程
- 设计目的:为 IOC 容器中 Bean 的实现提供更灵活的方式
二、核心区别
特性 | BeanFactory | FactoryBean |
---|---|---|
角色定位 | IoC 容器接口,Bean 的管理者 | 特殊的 Bean,用于创建其他 Bean |
主要功能 | 管理所有 Bean 的生命周期 | 定制特定 Bean 的创建逻辑 |
实现方式 | 作为容器接口,有多种实现类 | 实现 FactoryBean 接口的 Bean 类 |
使用方式 | 通过 getBean() 获取管理的 Bean | 注入时获取的是 getObject() 返回的对象 |
关注点 | 容器整体功能 | 特定 Bean 的创建细节 |
三、BeanFactory 详解
核心接口定义
BeanFactory 接口定义了 IoC 容器的基本操作:
java
public interface BeanFactory {
// 获取 Bean 的各种重载方法
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
// 检查 Bean 是否存在
boolean containsBean(String name);
// 判断 Bean 作用域
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 其他方法...
}
主要实现类
- DefaultListableBeanFactory:Spring 核心容器的默认实现,提供了 BeanFactory 的完整功能
- XmlBeanFactory:基于 XML 配置文件的 BeanFactory 实现(已弃用)
- ApplicationContext:BeanFactory 的子接口,提供更丰富的企业级功能
在项目中的应用
在本项目中,我们可以看到 BeanFactory 的使用示例(通过已弃用的 XmlBeanFactory):
java
// 创建 XmlBeanFactory
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
// 获取 Bean
UserService userService = (UserService) beanFactory.getBean("xmlUserService");
User user = (User) beanFactory.getBean("xmlSampleUser");
四、FactoryBean 详解
接口定义
java
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 返回由 FactoryBean 创建的 Bean 实例
@Nullable
T getObject() throws Exception;
// 返回 FactoryBean 创建的 Bean 类型
@Nullable
Class<?> getObjectType();
// 确定由 FactoryBean 创建的 Bean 实例是否为单例
default boolean isSingleton() {
return true;
}
}
工作原理
- 实现 FactoryBean 接口的类被注册为 Spring Bean
- 当通过
getBean()
获取该 Bean 时,Spring 返回的是getObject()
方法的返回值 - 若要获取 FactoryBean 本身的实例,需要使用
&
前缀,如getBean("&factoryBeanName")
自定义 FactoryBean 示例
下面是一个自定义 FactoryBean 的简单实现:
java
public class MyFactoryBean implements FactoryBean<Connection> {
private String url;
private String username;
private String password;
@Override
public Connection getObject() throws Exception {
// 自定义复杂对象的创建逻辑
return DriverManager.getConnection(url, username, password);
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return true; // 连接池模式下返回 true
}
// getter 和 setter 方法
}
五、FactoryBean 的典型应用场景
1. 封装复杂对象创建
当对象创建过程复杂、需要多个步骤或依赖外部资源时,使用 FactoryBean 可以很好地封装这些复杂性。
2. 框架集成
FactoryBean 在 Spring 与第三方框架集成时扮演着重要角色,以下是一些常见的例子:
MyBatis 的 SqlSessionFactoryBean
java
// Spring 配置
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(new ClassPathResource("mapper/*.xml"));
return factoryBean.getObject(); // 实际上返回的是 SqlSessionFactory
}
Feign 客户端工厂
Feign 通过 FactoryBean 创建动态代理的 REST 客户端:
java
@Bean
public FactoryBean<MyServiceClient> myServiceClient() {
FeignClientFactoryBean factory = new FeignClientFactoryBean();
factory.setUrl("http://example.com/api");
factory.setType(MyServiceClient.class);
return factory;
}
Redis 连接工厂
java
@Bean
public RedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName("localhost");
factory.setPort(6379);
return factory;
}
3. 动态代理创建
用于创建 AOP 代理对象、接口动态实现等场景:
java
public class ProxyFactoryBean<T> implements FactoryBean<T> {
private Class<T> interfaceClass;
@Override
public T getObject() throws Exception {
return (T) Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class<?>[] {interfaceClass},
(proxy, method, args) -> {
// 代理逻辑
System.out.println("方法调用前: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("方法调用后: " + method.getName());
return result;
}
);
}
// 其他方法实现
}
六、在 Spring 框架中的地位
BeanFactory
- 是 Spring IoC 容器的基础,所有的 IoC 容器都实现了这个接口
- 提供延迟加载特性(默认情况下)
- 提供基本的 Bean 管理功能
- ApplicationContext 是其扩展,提供更多企业级功能
FactoryBean
- 是 Spring IoC 容器实例化逻辑的扩展点
- Spring 自身提供了 70 多个 FactoryBean 的实现
- 在 Spring 的 AOP、ORM、事务管理等功能中广泛使用
- 是 Spring 框架与其他框架集成的重要桥梁
七、实际使用示例对比
使用 BeanFactory 获取普通 Bean
java
// 创建容器
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取 Bean
UserService userService = factory.getBean("userService", UserService.class);
使用 FactoryBean 创建复杂 Bean
java
// 1. 定义 FactoryBean
public class ConnectionFactoryBean implements FactoryBean<Connection> {
// 实现接口方法
}
// 2. 配置到 Spring
@Configuration
public class AppConfig {
@Bean
public ConnectionFactoryBean connectionFactory() {
return new ConnectionFactoryBean();
}
}
// 3. 使用(注入的是 Connection 而不是 ConnectionFactoryBean)
@Autowired
private Connection connection;
八、总结
- BeanFactory 是 IoC 容器的根接口,负责管理所有 Bean 的生命周期,是 Spring IoC 的基础设施
- FactoryBean 是一个特殊的 Bean,用于定制特定 Bean 的创建逻辑,简化复杂对象的配置和初始化
- 两者名称相似但职责完全不同:BeanFactory 是容器,FactoryBean 是特殊的 Bean
- 在实际开发中,我们通常使用 ApplicationContext(BeanFactory 的扩展)作为 IoC 容器,而 FactoryBean 则在需要定制 Bean 创建逻辑时使用
- 理解这两个概念对于深入掌握 Spring 框架的核心机制非常重要
虽然本项目中主要演示了 BeanFactory(和 ApplicationContext)的使用,没有直接展示 FactoryBean 的示例,但 FactoryBean 在 Spring 生态系统中的应用非常广泛,特别是在各种框架集成场景中。