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结尾,表示它是一个工厂类(接口),用于 ...
随机推荐
- 流批一体生产应用!Bigo 实时计算平台建设实践
简介: 本文由 Bigo 计算平台负责人徐帅分享,主要介绍 Bigo 实时计算平台建设实践的介绍 本文由 Bigo 计算平台负责人徐帅分享,主要介绍 Bigo 实时计算平台建设实践的介绍.内容包括: ...
- 实时 OLAP, 从 0 到 1
简介: BTC.com 团队在实时 OLAP 方面的技术演进过程及生产优化实践. 作者|高正炎 本文主要介绍 BTC.com 团队在实时 OLAP 方面的技术演进过程及生产优化实践,内容如下: 业务背 ...
- 更灵活的边缘云原生运维:OpenYurt 单元化部署新增 Patch 特性
简介: 在正文开始之前,我们先回顾一下单元化部署的概念和设计理念.在边缘计算场景下,计算节点具有很明显的地域分布属性,相同的应用可能需要部署在不同地域下的计算节点上. 作者 | 张杰(冰羽)来源 | ...
- 外部工具连接SaaS模式云数据仓库MaxCompute实战——商业BI分析工具篇
简介: MaxCompute 是面向分析的企业级 SaaS 模式云数据仓库,以 Serverless 架构提供快速.全托管的在线数据仓库服务,消除了传统数据平台在资源扩展性和弹性方面的限制,最小化用户 ...
- [FAQ] Cannot use object of type MongoInt64 as array
此类情况出现在 需要使用字符串/数组,实际却使用了对象. 解决方式是调试数据,对数据类型进行转换即可. MongoInt64 对象提供 __toString 方法,那么可以强转成 64 位 integ ...
- [Contract] Solidity 多种访问控制 (Access Control) 实现方式
在 solidity 中控制访问,一般是通过 modifier 修饰符方法来直接做. 那么对于稍复杂的多种访问控制,通常需要一个统一操作的模块化类库. 现在已经有了这样的类库存在,我们通过一个实现功能 ...
- dotnet 读 WPF 源代码笔记 WriteableBitmap 的渲染和更新是如何实现
在 WPF 框架提供方便进行像素读写的 WriteableBitmap 类,本文来告诉大家在咱写下像素到 WriteableBitmap 渲染,底层的逻辑 之前我使用 WriteableBitmap ...
- 为什么需要学习ITSM/ITIL
假如你需要管理一个超过20人的IT服务组织,一般会面临以下问题: 人多事杂活重,每个人都很累,工作却还是一团糟糕, 用户方怨声载道,领导也颇有微词,同事间也经常互相甩锅埋坑, 工作只是救火或者混日子, ...
- validator库在gin中的使用
目录 封装语言包翻译器 tag中设置验证规则 控制层验 curl请求 返回结果 封装语言包翻译器 package validator import ( "fmt" "ne ...
- 关于Java Chassis 3的契约优先(API First)开发
本文分享自华为云社区<Java Chassis 3技术解密:契约优先(API First)开发>,作者: liubao68. 契约优先(API First)开发是指应用程序开发过程中,将A ...