Spring扩展——BeanFactory和FactoryBean
BeanFactory和FactoryBean
BeanFactory和FactoryBean长得很相似,也很容易让我们产生误解,特别是对于初学者而言,搞懂他俩关系非常有必要,因为这两个接口,是Spring框架中非常重要的两个接口,也是很多同鞋在面试中经常被问到的问题
BeanFactory(bean工厂)
BeanFactory是Spring IOC容器中最基本的容器接口,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范,这当然也是Spring框架提供给我们日常开发最重要的一点,Spring框架通过BeanFactory来管理整个bean对象的生命周期,包括bean对象的实例化、初始化、销毁等等过程,也很好的为我们解决了Bean对象之间的相互依赖关系,提供多种属性注入的配置方式。

在Spring中还有一个非常重要的接口,ApplicationContext,Spring用它管理整个上下文,而通过阅读源码我们发现,在Spring中的ApplicationContext接口的具体实现类里面,有一个成员变量BeanFactory,我们通过ApplicationContext.getBean的方式来获取的bean对象的时候,实际上是把它交给了BeanFactory来间接获取的。

实际上我们可以这么理解,Spring通过BeanFactory来为我们管理Bean对象的生命周期,而Spring的ApplicationContext为我们的容器提供一个可靠的运行环境。
所以Spring的容器启动,可以简单地分为以下几个步骤
- ApplicationContext环境的准备;
- Bean容器的准备;
- 通过配置文件获取bean对象的定义信息;
- 将Bean定义信息注册到Bean容器中,也就是我们说的BeanFactory;
- 由BeanFactory创建bean对象,并管理bean对象(实例化、初始化、依赖注入等);
当然这中间还有许多的操作。
上面我们说过BeanFactory为我们的bean容器提供了管理Bean对象时最基本的规范,包括bean对象的实例化、初始化、属性注入、后置处理、销毁等等操作。在我们通过ApplicationContext.getBean方法获取bean对象的时候,我们发现实际它是交由BeanFactory来获取的。
实际上,为了加快getBean方法获取bean的速度,BeanFactory的实现类里面为我们提供了多种缓存。比如对于我们单例bean对象,在第一次创建成功后,就会将它放入BeanFactory的Map缓存里面,以便于后期再获取的时候,能够保证获取到的是同一对象,也就保证了bean的单例性。
FactoryBean(工厂bean)
FactoryBean接口,顾名思义工厂Bean,只看名字,我们就知道,它是用来描述bean类型,XXXBean,表示这是一个XXX类型的Bean。
所以我们可以猜出两点来
- 它肯定自身也是一个Bean对象
- 根据XXXBean理论得出,它应该是一个具有XXX功能或属性的Bean,这里XXX是Factory,所以它应该是一个具有创建其它Bean功能的一个Bean对象
public interface FactoryBean<T> {
/**
* 根据泛型返回一个此泛型的具体对象
*
* @return
* @throws Exception
*/
T getObject() throws Exception;
/**
* 获取Class类型
* @return
*/
Class<?> getObjectType();
/**
* 是否是单例
* @return
*/
default boolean isSingleton() {
return true;
}
}
根据上面猜出的结论,我们大致可以得出,只要实现了这个接口对象,它本身也应该是一个bean,应该交由Spring容器进行管理
在FactoryBean接口里面提供了3个方法,3个方法的用途请看代码里的注释
测试代码来一波
1.定义一个实现了FactoryBean接口的bean对象,通过注解的方式,name是teacherBeanFactory
@Component(value = "teacherBeanFactory")
public class Teacher implements FactoryBean<Student> {
@Override
public Student getObject() throws Exception {
return new Student("yan");
}
@Override
public Class<?> getObjectType() {
return Student.class;
}
/**
* 是否是单例,返回true
*
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
2.Student类,没有标注任何注解
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
}
2.通过注解的方式new一个ApplicationContext
public static void main(String[] args) {
//通过注解的方式启动一个Spring上下文
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Teacher.class);
String[] beanDefinitionNames = applicationContext.getBeanFactory().getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("name: "+beanDefinitionName + " bean: " + applicationContext.getBean(beanDefinitionName));
}
Teacher bean = applicationContext.getBean(Teacher.class);
System.out.println(bean);
}
3.打印输出(还有一些spring内部的bean没有写到这里)
name: teacherBeanFactory bean:com.mashibing.ycb.factorybean.Student@1963006a
com.mashibing.ycb.factorybean.Teacher@7fbe847c
我们可以看到,在Spring容器里面肯定存在两个不同的对象:1.Student 2.Teacher
for循环里面通过bean名称(teacherBeanFactory)获取到的bean居然是Student对象,很神奇吧。
正好印证了我们上面的猜测,FactoryBean不是一个简单的bean,它是一个可以创建其它bean的bean。
通过debug,我们发现在我们的BeanFactory的单例缓存(一级缓存)中,存在着Teacher类型的bean,名称就是我们刚刚在Teacher类上定义的名称——@Component(value = "teacherBeanFactory")
而在测试的时候,跟我们预期不一样的是,通过applicationContext.getBean("teacherBeanFactory")的时候,获取得到居然是一个Student的Bean对象。
其实在getBean的时候,有以下流程

可以看到Student对象的bean实际上是存放在factoryBeanObjectCache中的,并不是存放在SingletonMap(一级缓存)里的
结论
BeanFactory:BeanFactory顾名思义,它是一个工厂,一个bean工厂,描述的是一个工厂,而不是一个bean。它是负责生产和管理bean的一个工厂(很大的工厂,里面有很多的bean)。它是IOC容器最底层的接口,提供了对bean管理的基本规范。
FactoryBean:言而之,它是一个bean,一个带有创建功能的bean,描述的是一个bean,工厂只是它的一个修饰符,提供了一个创建bean的一个渠道,只是提供了一个渠道。
我们通俗点表达
机械厂——————生产很多种机械设备(包括数控机床)(BeanFactory)
数控机床——————生产特殊机械设备(FactoryBean)
如果有写得不准确的地方,请读者大胆在评论区指出
Spring扩展——BeanFactory和FactoryBean的更多相关文章
- Spring中BeanFactory与FactoryBean的区别
在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混. 一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层 ...
- 【Java面试】Spring中 BeanFactory和FactoryBean的区别
一个工作了六年多的粉丝,胸有成竹的去京东面试. 然后被Spring里面的一个问题卡住,唉,我和他说,6年啦,Spring都没搞明白? 那怎么去让面试官给你通过呢? 这个问题是: Spring中Bean ...
- Spring中BeanFactory与FactoryBean到底有什么区别?
一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean().containsBean()等管理Bea ...
- Spring的BeanFactory和FactoryBean
官方定义 BeanFactory:Spring Bean容器的根接口 FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例. 源码解 ...
- Spring之BeanFactory和FactoryBean接口的区别
目录 一.BeanFactory接口 二.FactoryBean接口 1.简单实现 2.增强实现 3.FactoryBean的实际使用案例 三.总结 @ Spring框架中的BeanFactory ...
- spring中BeanFactory和FactoryBean的区别
共同点: 都是接口 区别: BeanFactory 以Factory结尾,表示它是一个工厂类,用于管理Bean的一个工厂 在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器 ...
- BeanFactory 和FactoryBean的区别
转自:https://www.cnblogs.com/aspirant/p/9082858.html BeanFacotry是spring中比较原始的Factory.如XMLBeanFactory就是 ...
- Spring 的微内核与FactoryBean扩展机制--转载
作者:江南白衣 原文地址: http://www.blogjava.net/calvin/archive/2005/08/30/11099.html http://www.blogjava.net/c ...
- Difference between BeanFactory and FactoryBean in Spring Framework (Spring BeanFactory与Factory区别)
参见原文:http://www.geekabyte.io/2014/11/difference-between-beanfactory-and.html geekAbyte Codes and Ran ...
- Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于 ...
随机推荐
- Maxcompute-UNION数据类型对齐的方法
简介: 怎么对齐两段union脚本的数据类型 第1章 问题概述 1.1 UNION中隐式类型转换问题 近期参与的一个私有云项目要升级,因为maxcompute要升级到更新的版本,对之 ...
- 阿里云数字化安全生产平台 DPS V1.0 正式发布!
简介:数字化安全生产平台则帮助客户促进业务与 IT 的全面协同,从业务集中监控.业务流程管理.应急指挥响应等多维度来帮助客户建立完善专业的业务连续性保障体系. 作者:银桑.比扬 阿里云创立于 200 ...
- 走近Quick Audience,了解消费者运营产品的发展和演变
简介: Quick Audience产品是一款云原生面向消费者的营销产品,自诞生以来,经历了三个发展阶段.每个阶段的转变,都与互联网环境和消费者行为的变迁有着极大的关联. Quick Audien ...
- WPF控件:密码框绑定MVVM
以下是一种使用 MVVM 模式的方法: 首先,在 ViewModel 中添加一个属性来保存密码,我们可以使用 SecureString 类型. // 密码变量 private SecureString ...
- 用 SetWindowPos 方法设置一个停止响应的窗口将卡调用方
我使用 User32 的 SetWindowPos 方法去设置一个跨进程的窗口,这个窗口是停止响应的,将让调用的 SetWindowPos 方法卡住,不继续执行逻辑.通过堆栈分析是卡在 NtUserS ...
- WPF 使用 VideoDrawing 播放视频
本文告诉大家如何在 WPF 使用 VideoDrawing 进行视频播放 用这个方法有什么优势?其实只是想作为某个控件的背景,某个控件的背景使用视频而已 控件的背景使用 DrawingBrush 传入 ...
- FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
libass是一个适用于ASS和SSA格式(Advanced Substation Alpha/Substation Alpha)的字幕渲染器,支持的字幕类型包括srt.ass等,凡是涉及到给视频画 ...
- Golang 之 casbin(权限管理)
目录 1. 权限管理 官网 编辑器测试 1.1.1. 特征 Casbin的作用 Casbin不执行的操作 1.1.2. 怎么运行的 1.1.3. 安装 1. 示例代码 xormadapter 2. 示 ...
- BIN文件格式
BIN文件里面包含的只有代码生成的机器码,不像ELF文件或者obj文件一样还包含其他东西.MS-DOS.设备驱动文件以及操作系统的bootloader文件都是BIN文件. 在NASM中,BIN文件默认 ...
- ansible(17)--ansible的archive和unarchive模块
1. archive模块 功能:在远端主机打包与压缩: 主要参数如下: 参数 说明 path 要压缩的文件或目录 dest 压缩后的文件 format 指定打包压缩的类型:bz2.gz.tar.xz. ...