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

一文,讲清楚,beanfactory,factorybean,关联,区别 · 浏览次数 : 54

小编点评

**Bean 和 FactoryBean 的关联与区别** **Bean** 是 Spring 提供的接口,用于创建和管理 Bean。 **FactoryBean** 是一个实现 Bean 的接口,它可以从多个 Bean 创建一个新 Bean。 **主要区别:** | 特征 | Bean | FactoryBean | |---|---|---| | 创建方式 | 直接实例化 | 通过多个 Bean 创建 | | 功能 | 创建单个 Bean | 创建多个 Bean | | 主要用途 | 简单的 Bean 创建 | 复杂 Bean 创建或从多个 Bean 创建 | **举例:** ```java // Bean 接口 public interface Bean { // 创建 Bean 的方法 } // FactoryBean 接口 public interface FactoryBean { // 创建 Bean 的方法 } // 使用 BeanFactoryBean 创建 Bean public class ConfigLoaderFactoryBean implements FactoryBean { private String configLocation; // 设置配置位置 public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } // 获取 Bean 的方法 @Override public Bean getObject() throws Exception { // 解析 XML 配置 if (configLocation.startsWith("file:")) { return new LocalConfigLoader(); } else if (configLocation.startsWith("http:")) { return new RemoteConfigLoader(); } else { throw new IllegalArgumentException("Unsupported config location: " + configLocation); } } } ``` **总结:** BeanFactory 和 FactoryBean 是在 Spring 中用于创建和管理 Bean 的核心概念。 FactoryBean 是 Bean 的一种抽象,它可以帮助我们创建和管理多个 Bean,而 Bean 是 Spring 提供的接口,用于创建单个 Bean。

正文

本文分享自华为云社区 《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。

1.png

两者一个比较形象的比喻就是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注解。

2.png

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

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

三、BeanFactory

BeanFactory与ApplicationContext

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

3.png

尽管我们在日常项目中,使用的容器是具有更全功能的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 的关联与区别相似的内容:

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

BeanFactory 和 FactoryBean都包含一些Bean实例,除此之外其实没有什么相同的地方。

状态机的技术选型看这篇就够了,最后一个直叫好!!!

今天跟大家分享一个关于“状态机”的话题。给你讲清楚什么是状态机、为什么需要状态机、适用场景、有哪些具体的实现方案以及各个方案对比(附带github源码地址)

最短路三种算法详解

# 最短路 最短路问题即,给你一张图,让你求出图中两点的最短距离。 这篇文章会讲解 $Dijkstra$、$Spfa$、$Floyd$ 三种算法,让您透彻理解最短路! ## Dijkstra ### 朴素版 题目: ![image](https://img2023.cnblogs.com/blog/

产品代码都给你看了,可别再说不会DDD(七):实体与值对象

这是一个讲解DDD落地的文章系列,作者是《实现领域驱动设计》的译者滕云。本文章系列以一个真实的并已成功上线的软件项目——码如云(https://www.mryqr.com)为例,系统性地讲解DDD在落地实施过程中的各种典型实践,以及在面临实际业务场景时的诸多取舍。 本系列包含以下文章: DDD入门

数据库实验五:数据库编程

2、设计一个小型的数据库应用程序  可利用现有的数据库,也可重新设计数据库。  要求实现数据的增加、删除、修改、查询的功能。  在报告中描述清楚使用的数据库、数据表及实现的功能(要求截图,并附 代码) 设计一个小型的数据库应用程序 数据库名:student 表名:infor 字段: Sno:学

面试官:你讲下接口防重放如何处理?

前言 我们的API接口都是提供给第三方服务/客户端调用,所有请求地址以及请求参数都是暴露给用户的。 我们每次请求一个HTTP请求,用户都可以通过F12,或者抓包工具fd看到请求的URL链接,然后copy出来。这样是非常不安全的,有人可能会恶意的刷我们的接口,那这时该怎么办呢?防重放攻击就出来了。 什

能将三次握手讲到这个程度,不给你offer给谁!

摘要:在后端相关岗位的入职面试中,三次握手的出场频率非常的高,甚至说它是必考题也不为过。 本文分享自华为云社区《能将三次握手理解到这个深度,面试官拍案叫绝~》,作者:龙哥手记。 在后端相关岗位的入职面试中,三次握手的出场频率非常的高,甚至说它是必考题也不为过。一般的答案都是说客户端如何发起 SYN

数据分析er看过来,五款工具有你需要的

“我想转行做数据分析,但是我只会用Excel,不会其他的工具,有其他的数据分析工具推荐么?“ “我不会python,那我可以做数据分析吗” 大部分人对数据分析的的第一印象就是Excel,python,其实选择一个工具开始学习是需要花费学习成本的,如果不清楚这款工具能给你带来什么价值,就开始盲目学习,

装饰器模式:让你的对象变得更强大

在日常开发中,当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。这时候,我们该怎么办呢?我们可以使用装饰器器模式来解决这个问题,**本文将从以下四个方面讲解装饰器器模式**。 - 简介 - 优缺点 - 应用场景 -

某公司自动化测试3面

# 某公司自动化测试3面 > 仅供参阅,并不提供参考答案,上课的时候多数讲解过 > 算法题给了你一个参考,都是力扣上的 ## 一面 ```text 1. 自我介绍 2. 关于自动化:怎么做的,目前的进展,效果如何,遇到的困难 3. 你的框架搭建,最初是考虑了哪些因素去设计的 4. 如何维护自动化ca