我再详细深入地讲解一下 BeanFactory 和 FactoryBean 的区别,这次从源码层面和实际应用角度来分析:
1. 概念对比
BeanFactory
- 是什么:Spring IoC 容器的根接口
- 作用:负责 Bean 的创建、管理、依赖注入
- 定位:Spring 容器的基础设施
FactoryBean
- 是什么:一个特殊的 Bean,实现了
FactoryBean接口 - 作用:用于创建复杂的对象,是 Bean 的工厂
- 定位:自定义 Bean 创建逻辑的工具
2. 源码分析
BeanFactory 接口(简化版)
public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&"; // 获取 FactoryBean 本身的前缀Object getBean(String name) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;boolean containsBean(String name);boolean isSingleton(String name) throws NoSuchBeanDefinitionException;boolean isPrototype(String name) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;Class<?> getType(String name) throws NoSuchBeanDefinitionException;String[] getAliases(String name);}
FactoryBean 接口
public interface FactoryBean<T> {String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";@NullableT getObject() throws Exception; // 返回工厂生产的对象@NullableClass<?> getObjectType(); // 返回对象的类型default boolean isSingleton() { // 是否单例return true;}}
3. 核心区别
| 维度 | BeanFactory | FactoryBean |
|---|---|---|
| 本质 | Spring 容器的接口 | 一个特殊的 Bean |
| 职责 | 管理所有 Bean | 创建特定类型的 Bean |
| 继承关系 | 根接口 | 普通接口 |
| 使用方式 | 作为容器使用 | 实现接口后注册到容器 |
| 获取对象 | getBean("beanName") |
getBean("factoryBeanName") 返回其创建的对象 |
| 获取自身 | 不适用 | getBean("&factoryBeanName") |
4. 获取方式详解
获取 FactoryBean 创建的对象
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// MyFactoryBean 是一个 FactoryBeanMyObject obj = context.getBean("myFactoryBean"); // 返回 getObject() 的结果
获取 FactoryBean 本身
// 加上 "&" 前缀MyFactoryBean factory = context.getBean("&myFactoryBean");
Spring 源码中的处理逻辑(AbstractBeanFactory):
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// 如果是 FactoryBean 且请求的是工厂本身(以 & 开头)if (BeanFactoryUtils.isFactoryDereference(name)) {if (beanInstance instanceof NullBean) {return beanInstance;}if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}return beanInstance; // 返回 FactoryBean 本身}// 如果不是 FactoryBean,直接返回if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}// 如果是 FactoryBean,返回其创建的对象Object object = null;if (mbd != null) {mbd.isFactoryBean = true;}object = getObjectFromFactoryBean((FactoryBean<?>) beanInstance, beanName, !synthetic);return object;}
5. 实际应用示例
示例 1:自定义 FactoryBean 创建复杂对象
@Componentpublic class ConnectionFactoryBean implements FactoryBean<Connection> {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; }@Overridepublic Connection getObject() throws Exception {DriverManager.getConnection(url, username, password);}@Overridepublic Class<?> getObjectType() {return Connection.class;}@Overridepublic boolean isSingleton() {return false; // 每次获取都创建新连接}}
示例 2:Spring 内置的 FactoryBean
Spring 内部大量使用 FactoryBean,例如:
SqlSessionFactoryBean(MyBatis 集成):
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {@Overridepublic SqlSessionFactory getObject() throws Exception {return this.sqlSessionFactory;}@Overridepublic Class<?> getObjectType() {return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();}}
使用方式:
@Configurationpublic class MyBatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));return factoryBean;}}// 获取 SqlSessionFactorySqlSessionFactory sessionFactory = context.getBean(SqlSessionFactory.class);
6. FactoryBean 的生命周期
@Componentpublic class MyFactoryBean implements FactoryBean<MyObject>, InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("FactoryBean 初始化");}@Overridepublic MyObject getObject() throws Exception {System.out.println("创建 MyObject");return new MyObject();}@Overridepublic Class<?> getObjectType() {return MyObject.class;}@Overridepublic void destroy() throws Exception {System.out.println("FactoryBean 销毁");}}
执行顺序:
- FactoryBean 实例化
afterPropertiesSet()执行- 第一次
getBean()时调用getObject() - 容器关闭时调用
destroy()
7. 常见使用场景
① 创建第三方复杂对象
@Componentpublic class RedisConnectionFactoryBean implements FactoryBean<RedisConnection> {@Overridepublic RedisConnection getObject() throws Exception {return new JedisConnectionFactory().getConnection();}@Overridepublic Class<?> getObjectType() {return RedisConnection.class;}}
② 需要动态代理的对象
@Componentpublic class ProxyFactoryBean implements FactoryBean<Object> {private Object target;@Overridepublic Object getObject() throws Exception {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new MyInvocationHandler(target));}@Overridepublic Class<?> getObjectType() {return target.getClass();}}
③ 整合第三方框架
// Spring 整合 RabbitMQ@Beanpublic RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {return new RabbitAdmin(connectionFactory);}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {return new RabbitTemplate(connectionFactory);}
8. 总结对比图
┌─────────────────────────────────────────────────────────┐│ Spring 容器 ││ (BeanFactory) ││ ││ ┌─────────────────────────────────────────────────┐ ││ │ 普通 Bean │ ││ │ ┌─────────────────────────────────────────┐ │ ││ │ │ UserService │ │ ││ │ │ OrderService │ │ ││ │ └─────────────────────────────────────────┘ │ ││ └─────────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────────┐ ││ │ FactoryBean(特殊 Bean) │ ││ │ ┌─────────────────────────────────────────┐ │ ││ │ │ SqlSessionFactoryBean │ │ ││ │ │ └─> 创建 SqlSessionFactory │ │ ││ │ │ │ │ ││ │ │ ConnectionFactoryBean │ │ ││ │ │ └─> 创建 Connection │ │ ││ │ └─────────────────────────────────────────┘ │ ││ └─────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────┘
一句话总结
BeanFactory 是 Spring 容器本身,负责管理所有 Bean;FactoryBean 是一个特殊的 Bean,用于创建其他 Bean。当你需要自定义复杂对象的创建逻辑时,就实现 FactoryBean 接口。
希望这次更深入的解释能帮助你更好地理解这
正文完