FactoryBean 和BeanFactory的傻傻的总是分不清?

FactoryBean 是Spring框架中一个强大的接口,允许开发者自定义Bean的创建逻辑。通过实现接口,开发者可以创建复杂对象、实现延迟初始化、生成代理对象等。理解和正确使用可以极大地增强Spring应用的灵活性和可维护性。 阅读详情

引言

记得很久以前经常被问到这样一个面试题"FactoryBean 和BeanFactory它们有啥区别"。在 Spring 框架中,BeanFactory 和 FactoryBean 是两个核心概念,虽然名称相似,但它们的角色和功能完全不同。

1. 定义与角色

维度

BeanFactory

FactoryBean

角色

Spring 的 IoC 容器核心接口,负责管理所有 Bean 的生命周期(创建、配置、依赖注入)。

一个 特殊 Bean 接口,用于动态创建复杂对象(如代理对象、连接池、动态代理等)。

功能

提供容器基础能力(如 getBean()、containsBean() 等)。

通过 getObject() 方法返回实际需要的 Bean 实例。

接口方法

getBean()、containsBean()、isSingleton() 等。

getObject()、getObjectType()、isSingleton()。

典型实现

DefaultListableBeanFactory、ApplicationContext 等。

SqlSessionFactoryBean(MyBatis)、ProxyFactoryBean(AOP)等。


2. 核心区别

特性

BeanFactory

FactoryBean

获取对象的方式

直接返回容器中注册的 Bean 实例(如 getBean("beanName"))。

默认返回 getObject() 的结果(如 getBean("factoryBeanName"))。

访问自身的方式

直接通过 getBean("beanName") 获取。

需通过 &beanName 前缀获取(如 getBean("&factoryBeanName"))。

是否单例

容器默认管理 Bean 的作用域(如单例、原型)。

通过 isSingleton() 方法定义创建对象的作用域。

使用场景

管理所有 Bean 的基础设施(如依赖注入、生命周期管理)。

封装复杂对象的创建逻辑(如动态代理、数据库连接池)。


3. 使用场景与示例

(1) BeanFactory 的使用

  • 作用:作为 Spring 容器的根接口,负责管理所有 Bean 的生命周期。
  • 示例:
// 通过 BeanFactory 获取 Bean
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = factory.getBean("userService", UserService.class);

(2) FactoryBean 的使用

  • 作用:通过自定义 getObject() 方法创建复杂对象。
  • 示例:
// 定义 FactoryBean
public class MyConnectionFactory implements FactoryBean<Connection> {
    @Override
    public Connection getObject() throws Exception {
        // 返回数据库连接
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb");
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    @Override
    public boolean isSingleton() {
        return true; // 是否为单例
    }
}

// 配置到 Spring 容器
@Configuration
public class AppConfig {
    @Bean
    public FactoryBean<Connection> connectionFactory() {
        return new MyConnectionFactory();
    }
}

// 使用
@Autowired
private Connection connection; // 实际注入的是 getObject() 返回的 Connection

在 Spring 框架中,FactoryBean 被广泛用于集成第三方中间件或框架,通过封装复杂对象的创建逻辑,简化配置并提高灵活性。以下是几个常见中间件使用 FactoryBean 的示例:

1. MyBatis 的 SqlSessionFactoryBean

作用:
创建 MyBatis 的 SqlSessionFactory 实例,集成数据库配置、映射文件扫描等逻辑。

代码示例:

<!-- Spring 配置文件中定义 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

实现原理:

  • SqlSessionFactoryBean 实现了 FactoryBean<SqlSessionFactory>。
  • getObject() 方法内部调用 MyBatis 的 SqlSessionFactoryBuilder 创建 SqlSessionFactory。
  • 支持延迟加载和复杂配置(如多数据源、事务管理器)。

2. OpenFeign 的 FeignClientFactoryBean

作用:
动态创建 Feign 客户端(RESTful API 调用代理对象)。

代码示例:

@Configuration
public class FeignConfig {
    @Bean
    public FactoryBean<MyServiceClient> myServiceClient() {
        FeignClientFactoryBean factory = new FeignClientFactoryBean();
        factory.setUrl("http://example.com/api");
        factory.setType(MyServiceClient.class);
        return factory;
    }
}

实现原理:

  • FeignClientFactoryBean 封装了 Feign 的 Target 和 Encoder/Decoder 配置。
  • getObject() 返回动态代理的 Feign 客户端实例。
  • 支持自定义拦截器、重试策略等。

3. Redis 的 RedisConnectionFactoryBean

作用:
创建 Redis 连接池(如 JedisConnectionFactory 或 LettuceConnectionFactory)。

代码示例:

<!-- Spring 配置文件中定义 RedisConnectionFactoryBean -->
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="localhost"/>
    <property name="port" value="6379"/>
</bean>

实现原理:

  • JedisConnectionFactory 本身实现了 FactoryBean<RedisConnection>。
  • getObject() 返回 RedisConnection 实例(如 JedisConnection)。
  • 支持连接池配置(如最大连接数、超时时间)。

4. RocketMQ 的 RocketMQTemplate

作用:
封装 RocketMQ 生产者和消费者的创建逻辑。

代码示例:

@Configuration
public class RocketMQConfig {
    @Bean
    public RocketMQTemplate rocketMQTemplate() {
        RocketMQTemplate template = new RocketMQTemplate();
        template.setProducer(new DefaultMQProducer("my-producer-group"));
        template.setConsumer(new DefaultMQPushConsumer("my-consumer-group"));
        return template;
    }
}

实现原理:

  • RocketMQTemplate 通过 FactoryBean 模式初始化生产者和消费者。
  • getObject() 返回配置好的 RocketMQTemplate 实例。
  • 支持消息发送、监听器注册等操作。

5. Quartz 的 SchedulerFactoryBean

作用:
创建 Quartz 调度器(Scheduler),集成任务调度逻辑。

代码示例:

<!-- Spring 配置文件中定义 SchedulerFactoryBean -->
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="myCronTrigger"/>
        </list>
    </property>
</bean>

实现原理:

  • SchedulerFactoryBean 封装了 Quartz 的 SchedulerFactory 配置。
  • getObject() 返回 Scheduler 实例。
  • 支持动态注册任务和触发器。

6. Dubbo 的 ServiceBean

作用:
发布 Dubbo 服务,封装服务暴露和注册逻辑。

代码示例:

<!-- Spring 配置文件中定义 Dubbo ServiceBean -->
<bean id="dubboService" class="com.alibaba.dubbo.config.ServiceBean">
    <property name="interface" value="com.example.MyService"/>
    <property name="ref" ref="myServiceImpl"/>
</bean>

实现原理:

  • ServiceBean 实现了 FactoryBean<Exporter>。
  • getObject() 返回服务导出器(Exporter),完成服务注册和暴露。
  • 支持负载均衡、容错策略等 Dubbo 特性。

7. Kafka 的 KafkaTemplate

作用:
封装 Kafka 生产者和消费者的创建逻辑。

代码示例:

@Configuration
public class KafkaConfig {
    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(new ProducerFactory<>());
    }
}

实现原理:

  • KafkaTemplate 通过 FactoryBean 模式初始化生产者工厂。
  • getObject() 返回配置好的 KafkaTemplate 实例。
  • 支持消息发送、消费者监听等操作。

总结对比

中间件

FactoryBean 类型

作用领域

核心方法作用

MyBatis

SqlSessionFactoryBean

数据库访问

创建 SqlSessionFactory

OpenFeign

FeignClientFactoryBean

RESTful 客户端

创建 Feign 动态代理

Redis

JedisConnectionFactory

缓存/键值存储

创建 Redis 连接池

RocketMQ

RocketMQTemplate

消息队列

封装生产者/消费者逻辑

Quartz

SchedulerFactoryBean

定时任务调度

创建调度器并注册任务

Dubbo

ServiceBean

微服务 RPC

发布服务并注册到注册中心

Kafka

KafkaTemplate

消息队列

封装生产者/消费者逻辑

  • 解耦配置与逻辑:通过 FactoryBean 将复杂初始化逻辑封装,Spring 容器只需管理 Bean 的声明。
  • 支持动态创建:可根据运行时条件(如环境变量、配置参数)动态生成不同对象。
  • 统一资源管理:集中管理中间件的连接池、配置参数,便于维护和扩展。

4. 获取 FactoryBean 本身

  • 默认行为:getBean("factoryBeanName") 返回的是 FactoryBean.getObject() 的结果。
  • 获取 FactoryBean 实例本身:需在 Bean 名称前加 & 前缀。
// 获取 FactoryBean 创建的 Bean
Connection connection = context.getBean("connectionFactory", Connection.class);

// 获取 FactoryBean 实例本身
MyConnectionFactory factoryBean = (MyConnectionFactory) context.getBean("&connectionFactory");

5. 常见问题与解决方案

问题1:混淆 BeanFactory 和 FactoryBean 的功能

  • 解决方案:明确 BeanFactory 是容器,FactoryBean 是创建 Bean 的工具。

问题2:期望获取 FactoryBean 实例却得到其创建的 Bean

  • 示例:
// 错误:获取的是 Encryptor 实例,而非 FactoryBean
Encryptor encryptor = factory.getBean("encryptor");

// 正确:添加 "&" 前缀获取 FactoryBean
FactoryBean factoryBean = factory.getBean("&encryptor");

问题3:未正确实现 getObjectType() 导致类型检查失败

  • 修复:确保 getObjectType() 返回准确的类型信息。

6. 高级应用场景

(1) 动态代理生成

public class ServiceProxyFactoryBean implements FactoryBean<MyService> {
    @Override
    public MyService getObject() {
        return (MyService) Proxy.newProxyInstance(
            getClass().getClassLoader(),
            new Class[]{MyService.class},
            (proxy, method, args) -> {
                System.out.println("Before method: " + method.getName());
                return method.invoke(new MyServiceImpl(), args);
            });
    }
}

(2) 延迟初始化

public class LazyInitFactoryBean implements FactoryBean<ExpensiveBean> {
    private ExpensiveBean instance;

    @Override
    public ExpensiveBean getObject() {
        if (instance == null) {
            instance = new ExpensiveBean(); // 延迟初始化
        }
        return instance;
    }
}

7. 总结

维度

BeanFactory

FactoryBean

本质

Spring 容器的根接口,管理所有 Bean 的生命周期。

一个特殊 Bean,用于封装复杂对象的创建逻辑。

获取方式

getBean("beanName") 返回容器中的 Bean 实例。

getBean("factoryBeanName") 返回 getObject() 的结果,getBean("&factoryBeanName") 返回 FactoryBean 本身。

典型用途

Spring 容器的基础功能(如依赖注入、生命周期管理)。

创建动态代理、连接池、复杂对象等。

  • BeanFactory 是 Spring 容器本身,负责管理所有 Bean。
  • FactoryBean 是 容器中的一个 Bean,负责 生产其他 Bean。
  • &beanName 是访问 FactoryBean 本身的“密钥”。
【RT-DETR有效改进】利用MobileNetV3替换Backbone(轻量化网络结构,提点) 本文给大家带来的改进机制是,其主要改进思想集中在结合硬件感知的网络架构搜索(NAS)和NetAdapt算法,以优化移动设备CPU上的性能。它采用了新颖的架构设计,包括反转残差结构和线性瓶颈层,以及新的高效分割解码器Lite Reduced Atrous Spatial Pyramid Pooling(LR-ASPP),以提升在移动分类、检测和分割任务上的表现。实验表明,MobileNets在资源和准确性的权衡方面表现出色,并在多种应用(如对象检测、细粒度分类、面部属性识别和大规模地理定位)中展现了其有效性。 阅读详情

相关推荐

别再只跑Demo了!用MovieLens数据集完整复现一个电影推荐系统(Python/Pandas实战)

本文详细介绍了如何利用MovieLens数据集从零构建一个完整的电影推荐系统,涵盖数据清洗、特征工程、推荐算法实现(协同过滤和矩阵分解)以及Web服务部署的全流程。通过Python和Pandas实战,读者可以掌握推荐系统的核心技术和生产环境部署技巧,不再局限于简单的Demo运行。

weixin_29062865的博客 150

3分钟了解FactoryBean的作用和底层工作原理

大家好,我是冰点,本节我们通过对接口源码解析,以及使用示例剖析,让大家3分钟了解FactoryBean的作用和底层工作原理。以及FactoryBean的使用场景,学以致用。是Spring框架中的一个接口,用于创建和管理其他Bean实例的对象。的底层工作原理是通过实现接口并实现其中的方法来创建和管理Bean实例。以下是。

日拱一卒无有尽,功不唐捐终入海 3779

H桥电路原理

一、H桥原理 图1中所示为一个典型的直流电机控制电路。电路得名于“H桥式驱动电路”是因为它的形状酷似字母H。4个三极管组成H的4条垂直腿,而电机就是H中的横杠(注意:图1及随后的两个图都只是示意图,而不是完整的电路图,其中三极管的驱动电路没有画出来)。   如图所示,H桥式电机驱动电路包括4个三极管和一个电机。要使电机运转,必须导通对角线上的一对三极管。根据不同三极管对的导通情况,电流可能会从左...

Loadingzc的专栏 7万+

FactoryBean详解

FactoryBean也叫做Bean工厂,是用于生产Bean对象的类 FactoryBean的使用 首先我们要明确,FactoryBean也是一个Bean对象。我们如果要使用Bean工厂,可以手动实现一个实现FactoryBean接口的一个类。 @Component public class FactoryBean_test implements FactoryBean { @Override public Object getObject() throws Excepti...

m0_53127809的博客 1万+

Android Studio运行报错: failed to load include path ……\platforms\android-35\android.jar的最细解决方案

【代码】Android Studio运行报错: failed to load include path ……\platforms\android-35\android.jar的最细解决方案。

2401_86789230的博客 2万+

提高RFID检测距离以及检测速度的方法总结

摘要:提高RFID检测距离需优化阅读器功率、标签灵敏度、天线设计及频段选择,同时减少环境干扰;提升检测速度则需改进防碰撞算法、增强并行处理能力、精简数据传输。实际应用需平衡两者关系,如物流仓储采用UHF频段、高增益天线和动态Q算法实现远距离高速读取,ETC系统则通过微波频段和高速调制实现超远距离快速识别。不同场景需针对性优化硬件配置和系统参数。

start_up_go的博客 292

BeanFactory简单介绍

一、BeanFactory   BeanFactory,以Factory结尾,表示它是一个工厂类(接口),它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。 BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,...

LinDongTian 1万+

Test-Time Adaptation Induces Stronger Accuracy and Agreement-on-the-Line

TTA不管是否提高了OOD的泛化性都增强了线性的趋势,TTA的初始目的是为了增强OOD的表现,一个人可能会觉得TTA使得ACL更强的原因是他消除了ID和OOD之间的差距,因此所有模型间ID vs OOD的准确率接近于y=x这条线,但是实际上这个解释不能够反映我们的经验发现,因为虽然TTA将分布之间的偏移简化为一种放缩的分布,但是这个放缩的因子幅值可能很大,也就是α<<1但是r>>1,这就会导致很偏离y=x这条线,而且理论分析也是,虽然ID和OOD的差距很大,但是线性关系还在。

m0_62673638的博客 148

spring-FactoryBean的作用和使用场景,以及和BeanFactory的区别

BeanFactory和FactoryBean的区别、FactoryBean的作用

weixin_37862824的博客 9463

uniapp ios原生插件开发 (framework,cocoapods)

已知UniApp的插件开发方式有两种, 第一种 Xcode Framework的方式,这种方式是官方指定的方式。 这种方式的优点就是简单直接, 但也有不足,比如当插件需要引入一些三方库时,操作起来就不是那么方便。 而使用Cocoapods则可以很方便的引入三方库。 接下来,本文探索使用Cocoapods的方式来进行UniApp插件开发。

Rey的技术博客 9823

学Simulink--基于风力发电系统的场景实例:海上风电场在复杂海况下的动态响应仿真

本实例将创建一个针对海上风电场在复杂海况下的动态响应模型。该模型不仅考虑了不同风速条件的影响,还引入了波浪和水流对风机塔架及基础结构的影响。通过仿真验证系统的有效性,并探索最佳控制参数设置以提高整体性能和稳定性。本教程展示了如何在Simulink中实现一个海上风电场在复杂海况下的动态响应仿真模型,并分析其性能。通过这种方式,我们不仅可以验证所提出的技术手段在提高海上风电场稳定性和效率方面的有效性,还能进一步探索优化参数以适应特定的应用场景。

xiaoheshang_123的博客 168

FactoryBean 和 BeanFactory 的傻傻的总是分不清?

Spring 的。

m0_73735578的博客 1240

YOLOv11改进 | 模型知识蒸馏篇 | 利用模型蒸馏改进YOLOv11进行无损涨点 | 离线蒸馏(附代码 + 完整文件 + 解析教程)

这篇文章给大家带来的最新改进是模型的蒸馏,利用教师模型指导学生模型从而进行模型的涨点,本文的内容不仅可以用于论文中,在目前的绝大多数的工作中模型蒸馏是一项非常重要的技术,所以大家可以仔细学习一下本文的内容,本文从YOLOv8的项目文件为例,进行详细的修改教程,文章内包括完整的修改教程,针对小白我出了视频修改教程,如果你还不会我提供了修改后的文件大家直接运行即可,所以说不用担心不会适用!模型蒸馏真正的无损涨点,蒸馏你只看这一篇文章就足够了!欢迎大家订阅我的专栏一起学习YOLO!

Snu77的博客 4322

Spring 的 BeanFactory 和 FactoryBean 傻傻分不清

ApplicationContext接口,它由BeanFactory接口派生而来。 ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先。 BeanFactory和FactoryBean的区别 BeanFactory是接口,提供了OC容器最基本的形式,给具体的IOC容器的实现提供了规范,FactoryBean也是接口,为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装

CRMEB小程序商城的博客 332

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Spring 的 BeanFactory 和 FactoryBean 傻傻分不清?

BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。 ApplicationContext接口,它由BeanFactory接口派生而来。 ApplicationContext包含BeanFactory的所有功能,通常建议比Bea...

Java技术栈,分享最主流的Java技术 986

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: Spring Boot想入门是真容易吧,看完我这篇不就是手到擒来
下一篇: SpringBoot 加载外部 Jar,实现功能按需扩展!
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值