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的容器启动,可以简单地分为以下几个步骤

  1. ApplicationContext环境的准备;
  2. Bean容器的准备;
  3. 通过配置文件获取bean对象的定义信息;
  4. 将Bean定义信息注册到Bean容器中,也就是我们说的BeanFactory;
  5. 由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。

所以我们可以猜出两点来

  1. 它肯定自身也是一个Bean对象
  2. 根据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的更多相关文章

  1. Spring中BeanFactory与FactoryBean的区别

    在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混. 一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层 ...

  2. 【Java面试】Spring中 BeanFactory和FactoryBean的区别

    一个工作了六年多的粉丝,胸有成竹的去京东面试. 然后被Spring里面的一个问题卡住,唉,我和他说,6年啦,Spring都没搞明白? 那怎么去让面试官给你通过呢? 这个问题是: Spring中Bean ...

  3. Spring中BeanFactory与FactoryBean到底有什么区别?

    一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean().containsBean()等管理Bea ...

  4. Spring的BeanFactory和FactoryBean

    官方定义 BeanFactory:Spring Bean容器的根接口 FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例. 源码解 ...

  5. Spring之BeanFactory和FactoryBean接口的区别

    目录 一.BeanFactory接口 二.FactoryBean接口 1.简单实现 2.增强实现 3.FactoryBean的实际使用案例 三.总结 @   Spring框架中的BeanFactory ...

  6. spring中BeanFactory和FactoryBean的区别

    共同点: 都是接口 区别: BeanFactory 以Factory结尾,表示它是一个工厂类,用于管理Bean的一个工厂 在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器 ...

  7. BeanFactory 和FactoryBean的区别

    转自:https://www.cnblogs.com/aspirant/p/9082858.html BeanFacotry是spring中比较原始的Factory.如XMLBeanFactory就是 ...

  8. Spring 的微内核与FactoryBean扩展机制--转载

    作者:江南白衣 原文地址: http://www.blogjava.net/calvin/archive/2005/08/30/11099.html http://www.blogjava.net/c ...

  9. 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 ...

  10. Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法

    Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于 ...

随机推荐

  1. 超详攻略!Databricks 数据洞察 - 企业级全托管 Spark 大数据分析平台及案例分析

    简介: 5分钟读懂 Databricks 数据洞察 ~ 更多详细信息可登录 Databricks 数据洞察 产品链接:https://www.aliyun.com/product/bigdata/sp ...

  2. DataWorks 功能实践速览03期 — 生产开发环境隔离

    ​简介: DataWorks功能实践系列,帮助您解析业务实现过程中的痛点,提高业务功能使用效率! 往期回顾: DataWorks 功能实践速览01期--数据同步解决方案:为您介绍不同场景下可选的数据同 ...

  3. WPF开源轻便、快速的桌面启动器

    前言 今天大姚给大家分享一款WPF开源.简单.轻便.快速的桌面启动器(支持多主题.多语言:简体中文.繁体中文.英文等):CurvaLauncher. WPF介绍 WPF 是一个强大的桌面应用程序框架, ...

  4. [FAQ] Error: com.mysql.jdbc.Driver not loaded. :jdbc_driver_library

    以上问题出现在 logstash.conf 未配置好 MySQL 的 JDBC 驱动时导致的错误提示. 首先,下载好 MySQL JDBC 驱动库,可以放到 logstash.conf 所在当前目录或 ...

  5. dotnet 修复多框架 TargetFrameworks 包含不受支持平台导致构建失败

    本文将告诉大家如何修复 dotnet 项目里的多框架 TargetFrameworks 如果包含了当前系统无法支持的平台时,如何进行跳过.解决在 Linux 平台构建时提示 Mac Catalyst ...

  6. WPF 一千个矩形做动画测试性能

    在很多性能测试开始之前,都需要测试一下自己的期望优化的设备的性能上限是多少.我每次都是重新写一个测试应用,因为每次需要优化的方向都不相同.本文将记录一个我写的一个简单的测试应用,这里面包含了一千个半透 ...

  7. OpenAI未至,Open-Sora再度升级!已支持生成16秒720p视频

    Open-Sora 在开源社区悄悄更新了!现在支持长达 16 秒的视频生成,分辨率最高可达 720p,并且可以处理任何宽高比的文本到图像.文本到视频.图像到视频.视频到视频和无限长视频的生成需求.我们 ...

  8. 万字长文总结与剖析C语言关键字 -- <<C语言深度解剖>>

    C总结与剖析:关键字篇 -- <<C语言深度解剖>> 目录 C总结与剖析:关键字篇 -- <<C语言深度解剖>> 程序的本质:二进制文件 变量 1.变量 ...

  9. Node.js 万字教程

    0. 基础概念 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,使用了一个事件驱动.非阻塞式 I/O 模型,让 JavaScript 运行在服务端的开发平台. ...

  10. gorm使用小结

    增 db.Create(user) db.Save(user) 参数只能用**结构体指针****,因为要根据指针写入该条插入的数据, 所以user可以作为该条数据使用. 新增只能用结构体 save方法 ...