本文分享自华为云社区 《BeanFactory 和 FactoryBean 的关联与区别》,作者:战斧。

一、概括性的回答

两者其实都是Spring提供的接口,如下

public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}

BeanFactory 就是我们常说的Spring容器,其内包含着大量的Bean,我们可以从BeanFactory 获取到想要的Bean,或者查询Bean的一些信息。

而FactoryBean则是众多Bean里的一种,只不过这种Bean是一种辅助Bean或者说中间人,它的作用是为你提供另一个/一些Bean。

两者一个比较形象的比喻就是BeanFactory就是一家工厂,我们可以通过提供物品名字,从工厂中得到各式各样的物品,比如桌椅板凳,键盘鼠标 等等。而除此之外,我们还能获取一种比较特殊的物品——生产线(FactoryBean),一般情况下,我们获取生产线当然不是为了它本身,而是为了利用生产线生产出产品,所以当你提供生产线的名字,得到的其实是生产线生产的产品。当然,如果你就是想取这个生产线本身,那你提供的名字就得是 “&” + 生产线名。

二、FactoryBean

FactoryBean示例

我们先来看一下FactoryBean的基础用法,简而言之就是实现FactoryBean接口,然后重写其中的getObject方法,如下:

public class ConfigLoaderFactoryBean implements FactoryBean<ConfigLoader> {
private String configLocation; public void setConfigLocation(String configLocation) {
this.configLocation = configLocation;
} @Override
public ConfigLoader getObject() throws Exception {
if (configLocation.startsWith("file:")) {
LocalConfigLoader configLoader = new LocalConfigLoader();
configLoader.setFilePath(configLocation.substring(5));
return configLoader;
} else if (configLocation.startsWith("http:")) {
RemoteConfigLoader configLoader = new RemoteConfigLoader();
configLoader.setServerUrl(configLocation);
return configLoader;
} else {
throw new IllegalArgumentException("Unsupported config location: " + configLocation);
}
} @Override
public Class<?> getObjectType() {
return ConfigLoader.class;
}
}

然后把这个factoryBean放入容器中,你可以采用xml或者@Bean等形式注入。

<bean id="configLoader" class="com.example.ConfigLoaderFactoryBean">
<property name="configLocation" value="http://example.com/config.json"/>
</bean

FactoryBean的必要性

我们上面介绍过,FactoryBean其实相当于一个中间人,我们获取它,往往不是需要它本身,而是希望通过它获得另一个Bean,自然的我们会产生疑问,为什么要多此一举?如果我们通过它是为了获得另一个Bean,那么为什么不直接实例化另一个Bean然后放入Spring容器呢?比如在方法上使用@Bean注解。

这种想法无可厚非,主要是因为factoryBean接口的诞生更早,所以早期很多的结构采用了这种方式。后续有了@Bean注解以后,在方法上使用@Bean注解也能实现复杂Bean的创建了。

那是不是所有情况都能使用@Bean来替代factoryBean呢?比如我们想每次获取的Bean都是实时的,又比如我们需要一个计时器Bean,但你注入的Bean都被固定了,只有通过工厂,才能每次获取都能得到一个实时的新Bean。同样的,使用factoryBean还有一个懒加载的作用,对于某些复杂的Bean能在获取时再进行实例化。

三、BeanFactory

BeanFactory与ApplicationContext

提及BeanFactory,自然而然的我们会想到Spring的重要特性IOC,IOC要求有一个能管理所有Bean的管家,而管家需要一个盛放这些Bean的容器,这个容器就是BeanFactory。

尽管我们在日常项目中,使用的容器是具有更全功能的ApplicationContext,但ApplicationContext也是BeanFactory的子接口,其除了单纯的容器功能外,还有配置元信息,应用事件机制,资源管理等功能,所以我们可以说ApplicationContext是BeanFactory的增强版本。

BeanFactory的使用

在早期的spring项目中,我们经常会在代码中指定使用某种BeanFactory ,并且使用如下方式去加载资源。

 //读取核心的配置文件
ClassPathResource resource = new ClassPathResource("MyContext.xml");
BeanFactory BeanFactory = new XmlBeanFactory(resource);

顾名思义XmlBeanFactory就是能够读取并解析xml资源,解析出各种Bean后存入自身,而在后期,springboot的大规模使用后,其内置的工厂可以解析xml、properties以及注解等多种配置来源。

当然,其实Spring本身就有相当的自动化程度,比如当我们在启动类上使用。

@ImportResource(location = {"classpath:MyContext.xml"})

它也能导入内容,并根据资源后缀是否为".groovy"判断是使用GroovyBeanDefinitionReader.class 还是 XmlBeanDefinitionReader.class,对资源解析完成后,把Bean定义注册进BeanFactory中。

四、总结

我们应当发现了:BeanFactory 和 FactoryBean 除了名字相似、都能包含一些Bean实例之外,其实没有什么相同的地方。前者是SpringIOC的核心,是存放一切Bean的容器;后者只不过是对复杂Bean的一种包装,比如我们常用的myBatis组件,针对各个mapper级接口生成的Bean实例,就是以FactoryBean的形式存在Spring容器中的。

点击关注,第一时间了解华为云新鲜技术~

一文给你讲清楚BeanFactory 和 FactoryBean 的关联与区别的更多相关文章

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

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

  2. 一文读懂BeanFactory和FactoryBean区别

    一直以来,很多人对于Spring中的BeanFactory和FactoryBean都是分不清楚的 BeanFactory 这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一 ...

  3. spring:Beanfactory和ApplicationContext、BeanFactory 和 FactoryBean

    1.Beanfactory和ApplicationContext有什么区别 ApplicationContext (1)在配置文件加载后创建bean 利用debug方式,在Student类的无参构造方 ...

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

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

  5. BeanFactory和FactoryBean

    BeanFactory和FactoryBean 1.BeanFactory BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring I ...

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

  7. BeanFactory和FactoryBean的区别

    转自:http://blog.csdn.net/wangbiao007/article/details/53183764 1.BeanFactory BeanFactory是IOC最基本的容器,负责生 ...

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

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

  9. Spring中BeanFactory与FactoryBean的区别

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

  10. Spring BeanFactory 与 FactoryBean 的区别

    BeanFactory 和 FactoryBean 都是Spring Beans模块下的接口 BeanFactory是spring简单工厂模式的接口类,spring IOC特性核心类,提供从工厂类中获 ...

随机推荐

  1. tryhackme-Agent Sudo

    描述:您在深海下发现了一个秘密服务器.你的任务是侵入服务器内部并揭露真相. 枚举 nmap -sV -T4 -v 10.10.123.164 NSE: Script scanning 10.10.12 ...

  2. [Kotlin Tutorials 21] 协程的取消

    协程的取消 本文讨论协程的取消, 以及实现时可能会碰到的几个问题. 本文属于合辑: https://github.com/mengdd/KotlinTutorials 协程的取消 取消的意义: 避免资 ...

  3. Python潮流周刊#6:Python 3.12 有我贡献的代码!

    你好,我是猫哥.这里记录每周值得分享的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 首发于我的博客,https://pyt ...

  4. 揭秘Spring依赖注入和SpEL表达式

    摘要:在本文中,我们深入探讨了Spring框架中的属性注入技术,包括setter注入.构造器注入.注解式属性注入,以及使用SpEL表达式进行属性注入. 本文分享自华为云社区<Spring高手之路 ...

  5. 消失的死锁:从 JSF 线程池满到 JVM 初始化原理剖析

    一.问题描述 在一次上线时,按照正常流程上线后,观察了线上报文.接口可用率十分钟以上,未出现异常情况,结果在上线一小时后突然收到jsf线程池耗尽的报警,并且该应用一共有30台机器,只有一台机器出现该问 ...

  6. Java Websocket 02: 原生模式通过 Websocket 传输文件

    目录 Java Websocket 01: 原生模式 Websocket 基础通信 Java Websocket 02: 原生模式通过 Websocket 传输文件 Websocket 原生模式 传输 ...

  7. CSS3+Jquery实现带动画效果的下拉选择框

    CSS3+JQuery实现带动画效果的下拉选择框. 元素结构为: 1 <div class="box"> 2 <p>this is the first li ...

  8. FPGA加速技术:在数据中心和云计算中的应用

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 3.1 准备工作:环境配置与依赖安装 3.2 核心模块实现 3.3 集成与测试 4. 应用示例与代码实现讲解 4.1. 应用场景介绍 4. ...

  9. ELK8.8部署安装并配置xpark认证

    ELK8.8部署安装并配置xpark认证 介绍   主要记录下filebeat+logstash+elasticsearch+kibana抽取过滤存储展示应用日志文件的方式:版本基于8.8,并开启xp ...

  10. FFmpeg合并视频和音频文件

    使用IDM下载Bilibili的视频会出现音视频分离的问题,通常文件大的是视频(没有声音),文件小的是单独的音频. 将两个文件都下载下来后,可以使用FFmpeg将其合并成一个视频文件.首先去FFmpe ...