Spring中BeanFactory FactoryBean和ObjectFactory的三种的区别
作者:njitzyd 发布时间:2022-02-21 22:43:58
Spring中BeanFactory FactoryBean和ObjectFactory的三种的区别
引言
关于FactoryBean 和 BeanFactory的对比文章比较多,但是对ObjectFactory的描述就比较少,今天我们对比下这三种的区别。
结论
BeanFactory就是对象工厂,Spring的底层容器,用于实例化和保存对象。
FactoryBean是一个工厂对象,用于实例化创建过程比较复杂的对象,对象的创建过程是由用户自己控制的。
ObjectFactory是某个特定的工厂,用于在项目启动时,延迟实例化对象,解决循环依赖问题,也就是 * 缓存那里会用到,以及结合Scope,灵活方便的实现是否需要创建对象。
BeanFactory
Spring最最核心的接口,Bean工厂,从名字上就能看出这是一个工厂。它是Spring最底层的容器,负责实例化和保存Spring中的Bean。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
## 方法很多,不再赘述
}
FactoryBean
public interface FactoryBean<T> {
//返回的对象实例
T getObject() throws Exception;
//Bean的类型
Class<?> getObjectType();
//true是单例,false是非单例 在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
boolean isSingleton();
}
我们观察到FactoryBean接口有三个方法。getObject
用来返回实例化后的对象。getObjectType
用来返回对象的类型。isSingleton
用来标识对象是否为单例的,这里默认为true,Spring会将实例化后的对象放入BeanFactory容器中。
从方法上,能推测出,这个凡是实现了FactoryBean接口的类,负责返回这个java类的实例化对象。
从设计模式的角度来看这就是典型的工厂方法模式。由一个特定的工厂来生产特定的java类的实例化对象。
那么这种写法有哪些好处呢?
正常情况下,Spring中在实例化对象的时候,都是由BeanFactory从上下文中获取BeanDefinition信息,然后通过反射,调用这个java类的构造方法进行实例化。而现在这种形式,我们相当于将实例化的功能交给了FactoryBean去实现。这种方式主要使用在一些比较复杂的实例化过程中,并非简单地设置一些参数或者设置的参数过多,过程中可能需要做一些复杂的解析、判断和逻辑处理,这个时候交由Spring去通过反射进行实例化可能就不太灵活了,
Spring容器中有两种Bean,一种是普通的Bean对象,一种是实现了FactoryBean的工厂Bean对象。如果从BeanFactory中getBean的时候,获取到的Bean对象是工厂Bean,会自动的调用它的getObject方法返回真实实例化对象。
如果就是需要获取FactoryBean对象,需要在getBean的时候加上前缀’&'。
Spring自身就对FactoryBean有70多种实现,比较常见的就是Proxy,Jndi等场景。
AOP中使用的ProxyFactoryBean。
Dubbo中使用的ReferenceBean。
Mybatis中使用的SqlSessionFactoryBean。
FactoryBean的着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的话spring会利用单例缓存来缓存通过FactoryBean创建的对象。
ObjectFactory
public interface ObjectFactory<T> {
//返回的对象实例
T getObject() throws BeansException;
}
这用于延迟查找的场景,它就是一个普通工厂,当得到 ObjectFactory 对象时,相当于 Bean 没有被创建,只有当 getObject() 方法时,才会触发 Bean 实例化等生命周期。
一方面在循环依赖的时候,用于延迟初始化,见org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
中调用addSingletonFactory
方法,会把ObjectFactory的Lambda表达式放入 * 缓存。
另一方面,在AbstractBeanFacotry在doGetBean处的使用时,将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope。除此之外ObjectFactory就是一个普通的接口
简单来说就是通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机也可以用来延迟初始化来解决循环依赖问题。
参考
BeanFactory和FactoryBean对比
补充介绍spring中关于FactoryBean 和 ObjectFactory的认识和区别
FactoryBean:
这个接口使你可以提供一个复杂的逻辑来生成 Bean。它本质是一个 Bean,但这个 Bean 不是用来注 入到其它地方像 Service、Dao 一样使用的,它是用来生成其它 Bean 使用的。实现了这个接口后, Spring 在容器初始化时,把实现这个接口的 Bean 取出来,使用接口的 getObject()方法来生成我们 要想的 Bean。当然,那些生成 Bean 的业务逻辑也要写 getObject()方法中。 其返回的对象不是指定类的一个实例,其返回的是该工厂 Bean 的 getObject 方法所返回的对象。创 建出来的对象是否属于单例由 isSingleton 中的返回决定。
使用场景:
1、通过外部对类是否是单例进行控制,该类自己无法感知
2、在创建 Object 对象之前进 行初始化的操作,在 afterPropertiesSet()中完成。(一次性的初始化,保存在成员变量中,并不是 每次 getObject 都会调用 afterPropertiesSet,afterPropertiesSet 只会被调用一次)
ObjectFactory:
它的目的也是作为一个工厂,来生成 Object(这个接口只有一个方法 getObject())。这个接口一般被 用来,包装一个 factory,通过个这工厂来返回一个新实例(prototype 类型)。这个接口和 FactoryBean 有点像,但 FactoryBean 的实现是被当做一个 SPI(Service Provider Interface)实例来使用在 BeanFactory 里面;ObjectFactory 的实现一般被用来注入到其它 Bean 中,作为 API 来使用。就像ObjectFactoryCreatingFactoryBean 的 例 子 , 它 的 返 回 值 就 是 一 个 ObjectFactory , 这 个 ObjectFactory 被注入到了 Bean 中,在 Bean 通过这个接口的实例,来取得我们想要的 Bean。
总的来说,FactoryBean 和 ObjectFactory 都是用来取得 Bean,但使用的方法和地方不同, FactoryBean 被配置好后,Spring 调用 getObject()方法来取得 Bean,ObjectFactory 配置好后, 在 Bean 里面可以取得 ObjectFactory 实例,需要我们手动来调用 getObject()来取得 Bean。
来源:https://blog.csdn.net/qq_37687594/article/details/128695678
猜你喜欢
- 本文实例为大家分享了Unity实现俄罗斯方块第2部分,供大家参考,具体内容如下代码部分1. 实现物体自由降落(在有关于物体的脚本中编写)1)
- 前言无论Spring的XML配置或者Java配置,都可以配置自动扫描,也就是在指定包及其子包下的component,都会被自动扫描并被Spr
- 1 问题实现任意view经过自定义带4圆角或者2圆角的效果2 原理1) 实现view 4圆角我们只需要把左边的图嵌入到右边里面去,最终显示左
- 1. Spark中的RDDResilient Distributed Datasets(弹性分布式数据集)Spark中的最基本的抽象有了RD
- 字体池的应用,主要是为了解决字体不断创建导致句柄泄漏/内存泄漏的问题,这个问题在Android上也同样存在。经测试,C# WinForm原生
- 本文实例讲述了Java解析Excel内容的方法。分享给大家供大家参考。具体实现方法如下:import java.io.File;
- IComparable<T>.NET 里,IComparable<T>是用来作比较的最常用接口。如果某个类型的实例需
- Android中判断当前网络是否可用 应用场景:实现判断当前网络是否可用当前有可用网络,如下图:当前没有可用网络,如下图:实现步骤:1、获取
- 前言MyBatis提供了9种动态SQL标签:trim、where、set、foreach、if、choose、when、otherwise、
- JSONObject toJSONString错误1.com.alibaba.fastjson.JSONObject 继承了JSON可以使用
- 在混淆编译之前,我的程序可以正常运行,混淆编译时,报告如下错误: Error:Execution failed for task ‘:gvi
- mybatis 报错显示sql中有两个limit使用mybatis进行分页查询时,打印的查询sql中带有两个limit。经过审查:原因是由于
- Java是面向对象的编程语言,在我们开发Java应用的程序员的专业术语里,Java这个单词其实指的是Java开发工具,也就是JDK(Java
- 前言目前,企业项目的开发过程中,往往会使用配置文件来做一些配置项来实现项目部署的灵活性,避免硬编码的方式在环境变化时需要对代码进行重新编译。
- 实现说明这里的核心在于如何在大并发的情况下保证数据库能扛得住压力,因为大并发的瓶颈在于数据库。如果用户的请求直接从前端传到数据库,显然,数据
- 1.修改系统默认的Dialog样式(风格、主题)2.自定义Dialog布局文件3.可以自己封装一个类,继承自Dialog或者直接使用Dial
- 在很多语音视频软件系统中,经常有将实时的音频或视频录制为文件保存到磁盘的需求,比如,视频监控系统中录制监控到的视频、视频会议系统中录制整个会
- The error simply says, “you've made changes in files in your works
- 简介本文用示例介绍SpringMVC如何通过JSON格式传递入参。JSON格式使用post方式来请求,即:对应的注解为:@PostMappi
- 注意:不同的JDK版本的扩容机制可能有差异实验环境:JDK1.8扩容机制:当向ArrayList中添加元素的时候,ArrayList如果要满