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. Forrester云原生开发者洞察白皮书,低代码概念缔造者又提出新的开发范式

    简介: 云原生时代的到来为开发者群体带来了前所未有的机遇,让开发者可以更加专注业务价值创造与创新,并使得人人成为开发者成为现实.广大开发者如何转型成为云原生开发者?运维等专业人员在云原生时代如何避免边 ...

  2. [FAQ] Vmmem 内存占用高的问题 -Win10 -WLS2

    1按下Windows + R 键,输入 %UserProfile% 并运行进入用户文件夹 2新建文件 .wslconfig ,然后记事本编辑 3 填入以下内容并保存, memory为系统内存上限,这里 ...

  3. [FAQ] 夏玉米 按规则查询域名靠谱吗 ?

    很早就有一个网站叫 夏玉米,可以按规则查询和注册域名,那么它真如我们想的那样 可以找到好域名吗? 虽然看起来很好用,实际上夏玉米的查询只是针对它自己的数据库,不包含未在其平台注册的域名,所以大家要失望 ...

  4. WPF 使用 Skia 解析绘制 SVG 图片

    本文告诉大家如何在 WPF 里面,使用 Skia 解析绘制 SVG 图片.本文也适合控制台使用 SkiaSharp 解析绘制 SVG 图片,本文的 WPF 部分只是在 Skia 绘制完成之后,将 Sk ...

  5. JavaScript字符串String方法介绍及使用示例

    实例方法 charAt() charCodeAt() 返回索引位置的字符 'hello'.charAt(0) //h 等价 'hello'.[0] //返回索引位置的字符的Unicode码点 'hel ...

  6. kafka connect gui 可视化管理工具

    kafka connect gui 可视化管理工具 官网地址:http://www.redisant.cn/ka 连接到 Kafka Connect 支持各种认证方式,支持 SSL/TLS 安全连接 ...

  7. K8s集群中部署SpringCloud在线购物平台(二)

    三.harbor简介 harbor 是私有镜像仓库,用来存储和分发镜像的 docker 还有一个官方的镜像仓库 docker hub,免费用户只能简单的使用,创建一个私有镜像仓库,存储 镜像,付费用户 ...

  8. netcore5下js请求跨域

    后端代码如下: using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System ...

  9. 从[SDOI2011]消防 到[NOIP2007]树网的核

    有关消防一题中最优解一定在直径上的证明 P2491 [SDOI2011] 消防 P1099 [NOIP2007 提高组] 树网的核 题目描述 在一颗 \(n\) 个节点的无根树中,找到一条不超过 \( ...

  10. vue3早已具备抛弃虚拟DOM的能力了

    前言 jquery时代更新视图是直接对DOM进行操作,缺点是频繁操作真实 DOM,性能差.react和vue时代引入了虚拟DOM,更新视图是对新旧虚拟DOM树进行一层层的遍历比较,然后找出需要更新的D ...