简单了解Spring中BeanFactory与FactoryBean的区别

这篇文章主要介绍了简单了解Spring中BeanFactory与FactoryBean的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混。

一、BeanFactory

BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean()、containsBean()等管理Bean的通用方法。Spring的容器都是它的具体实现如:

  • DefaultListableBeanFactory
  • XmlBeanFactory
  • ApplicationContext

这些实现类又从不同的维度分别有不同的扩展。

1.1 BenaFactory源码

public interface BeanFactory {

  /**
   * 用来获得实例的引用,并且区分FactoryBean区分。
   * 如果使用bean的名字myJndiObject获取FactoryBean,返回的是一个工厂,而不是工厂的实例;如果需要获得工厂实例,需要转义。
   */
  String FACTORY_BEAN_PREFIX = "&";

  /**
   * 根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.
   */
  Object getBean(String name) throws BeansException;

  /**
   * 根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.并且增加了一个类型的检验。
   */
  <T> T getBean(String name, Class<T> requiredType) throws BeansException;

  Object getBean(String name, Object... args) throws BeansException;

  /**
   * 根据给定类型返回匹配的bean实例.
   */
  <T> T getBean(Class<T> requiredType) throws BeansException;

  <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

  /**
   * 检查spring的bean容器中是否包含有该bean
   */
  boolean containsBean(String name);

  /**
   * 判断bean的作用域是否是singleton
   */
  boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

  /**
   * 判断bena的作用域是否是prototype
   */
  boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

  /**
   * 检查给定名称的bean是否和指定类型匹配.更确却的说是通过检查给定的bean,返回指定类型的目标对象
   */
  boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

  boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

  /**
   * 获取给定名称的bean的class类型
   */
  Class<?> getType(String name) throws NoSuchBeanDefinitionException;

  /**
   * 获取给定bean名称的别名,如果根据别名检索,将会获得原始bean名称。
   *
  String[] getAliases(String name);

}

1.2 使用场景

  • 从Ioc容器中获取Bean(byName or byType):context.getBean("father", Father.class)、context.getBean("father")
  • 检索Ioc容器中是否包含指定的Bean: context.containsBean("father")
  • 判断Bean是否为单例: context.isSingleton("father")

二、FactoryBean

首先它是一个Bean,但又不仅仅是一个Bean。它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。

2.1 FactoryBean源码

public interface FactoryBean<T> {

  /**
   * 从工厂中获取bean实例
   */
  T getObject() throws Exception;

  /**
   * 从工厂中获取bean实例对象的类型
   */
  Class<?> getObjectType();

  /**
   * 工厂创建的对象是否是单例
   */
  boolean isSingleton();

}

从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上'&'符号。

  • getObject('name')返回工厂中的实例
  • getObject('&name')返回工厂本身的实例

通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

2.2 示例

先定义一个Bean实现FactoryBean接口:

@Component
public class MyBean implements FactoryBean {
  private String message;
  public MyBean() {
    this.message = "通过构造方法初始化实例";
  }

  public MyBean(String message) {
    this.message = message;
  }

  @Override
  public Object getObject() throws Exception {
    // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例
    return new MyBean("通过FactoryBean.getObject()创建实例");
  }
  @Override
  public Class<?> getObjectType() {
    return MyBean.class;
  }
  public String getMessage() {
    return message;
  }

  @Override
  public boolean isSingleton() {
    return false;
  }
}

MyBean实现了FactoryBean接口的三个方法,getObject()是可以返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。然后测试代码中先通过名称获取Bean实例,打印message的内容,再通过&+名称获取实例并打印message内容。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HelloApplication.class)
public class FactoryBeanTest {
  @Autowired
  private ApplicationContext context;
  @Test
  public void test() {
    MyBean myBean1 = (MyBean) context.getBean("myBean");//返回工厂中的实例,调用FactoryBean.getObject()创建实例
    System.out.println("myBean1 = " + myBean1.getMessage());
    MyBean myBean2 = (MyBean) context.getBean("&myBean");//返回工厂本身,通过构造方法初始化实例
    System.out.println("myBean2 = " + myBean2.getMessage());
    System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
  }
}

打印结果:

myBean1 = 通过FactoryBean.getObject()创建实例
myBean2 = 通过构造方法初始化实例
myBean1.equals(myBean2) = false

2.3 使用场景

说了这么多,为什么要有FactoryBean这个东西呢,有什么具体的作用吗?

FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象。

我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean。

所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。

三、区别

  • 他们两个都是个工厂,但FactoryBean本质上还是一个Bean,也归BeanFactory管理
  • BeanFactory是Spring容器的顶层接口,FactoryBean更类似于用户自定义的工厂接口。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot单体架构http请求转换https请求来支持微信小程序调用接口

    http请求转换https请求 1.话不多说,直接上代码! application.properties配置文件 #(密钥文件路径,也可以配置绝对路径) server.ssl.key-store= classpath:证书文件名.pfx #(密钥生成时输入的密钥库口令) server.ssl.key-store-password:123456 #(密钥类型,与密钥生成命令一致) server.ssl.key-store-type:PKCS12 证书一般最好放在resources目录下 接下来配置

  • springboot调用支付宝第三方接口(沙箱环境)

    springboot+调用支付宝第三方接口(沙箱环境) 大神勿喷!! 网址:https://developers.alipay.com/platform/developerIndex.htm 沙箱环境中给测试提供了一些必要和非必要的参数,需要自己动手修改的只有RSA密钥,需要通过支付宝提供的开发工具生成RSA密钥,下载链接:https://docs.open.alipay.com/291/105971#LDsXr 下载完成安装之后,可以生成RSA密钥.生成的密钥分为应用公钥,应用私钥.应用私钥自

  • spring中的BeanFactory与FactoryBean的讲解

    1.BeanFactory 1.1Spring提供了IOC容器的两种实现方式 ① BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的. ② ApplicationContext:BeanFactory的子接口,提供了更多高级特性.面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory. 1.2 ApplicationContext的主要实现类 ClassPath

  • Spring Boot配置接口WebMvcConfigurer的实现

    WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制.基于java-based方式的spring mvc配置,需要创建一个配置类并实现WebMvcConfigurer 接口,WebMvcConfigurerAdapter 抽象类是对WebMvcConfigurer接口的简单抽象(增加了一些默认实现),但在在SpringBoot2.0及Spring5.0中WebMvcConfigurerAdapt

  • Spring中BeanFactory与FactoryBean接口的区别详解

    前言 Spring框架中的BeanFactory接口和FactoryBean接口因为名称相似,老是容易搞混淆,而且也是面试过程中经常会碰到的一个问题.所以本文就专门给大家整理出来. 一.BeanFactory接口 BeanFactory接口是Spring容器的核心接口,负责:实例化.定位.配置应用程序中的对象及建立这些对象间的依赖. Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系.

  • Spring Cloud Feign接口返回流的实现

    服务提供者 @GetMapping("/{id}") public void queryJobInfoLogDetail(@PathVariable("id") Long id, HttpServletResponse response) { File file = new File("xxxxx"); InputStream fileInputStream = new FileInputStream(file); OutputStream ou

  • SpringBoot下如何实现支付宝接口的使用

    这篇文章主要介绍了SpringBoot下如何实现支付宝接口的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前期准备: 参考之前写过的 支付宝接口引入servlet版本 Jar包引入: <!-- 支付宝 --> <dependency> <groupId>net.guerlab</groupId> <artifactId>sdk-alipay-starter</artifactId&g

  • spring boot 统一JSON格式的接口返回结果的实现

    前后端分离的项目开发前,会提前规定好数据返回格式,本文以JSON为例. 第一步,定义好JavaBean. package com.yclouds.myhelper.web.response; import com.fasterxml.jackson.annotation.JsonIgnore; import com.yclouds.myhelper.web.error.code.BaseEnumError; import java.io.Serializable; import lombok.D

  • 简单了解Spring中BeanFactory与FactoryBean的区别

    这篇文章主要介绍了简单了解Spring中BeanFactory与FactoryBean的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混. 一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean().containsBean()等管理Be

  • Spring BeanFactory 与 FactoryBean 的区别详情

    目录 区别和联系 BeanFactory FactoryBean 总结 前言: 在 Spring 中, IOC 是很重要的概念,其本质就是 map 结构,存储容器和业务 Bean 信息.但是 BeanFactory 和 FactoryBean 的区别却是一个很重要的知识点,在本文中将结合源码进行分析讲解. 区别和联系 BeanFactory 在 Spring 中,所有的 Bean 都是由 BeanFactory (也就是 IOC 容器)来进行管理的.BeanFactory 定义了容器的基本形式,

  • 简单了解Spring中常用工具类

    文件资源操作 Spring 定义了一个 org.springframework.core.io.Resource 接口,Resource 接口是为了统一各种类型不同的资源而定义的,Spring 提供了若干 Resource 接口的实现类,这些实现类可以轻松地加载不同类型的底层资源,并提供了获取文件名.URL 地址以及资源内容的操作方法 访问文件资源 * 通过 FileSystemResource 以文件系统绝对路径的方式进行访问: * 通过 ClassPathResource 以类路径的方式进行

  • Spring中BeanFactory和ApplicationContext的作用和区别(推荐)

    作用: 1.BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期.2.ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能: a. 国际化支持 b. 资源访问:Resource rs = ctx. getResource("classpath:config.properties"), "file:c:/config.properties&qu

  • BeanFactory和FactoryBean的区别示例详解

    目录 正文 BeanFactory和FactoryBean的区别 1.BeanFactory 2.FactoryBean 正文 这个之前经常会遇到别人问 但是一直不是很能理解 工作开发中我对于bean的使用比较少 就是偶尔启动出错才会出现 可能是水平有限 但是bean 也是非常核心的问题 书到用时方恨少 且看且珍惜 BeanFacotry是spring中比较原始的Factory. 如XMLBeanFactory就是一种典型的BeanFactory.原始的BeanFactory无法支持spring

  • 简单了解java中int和Integer的区别

    这篇文章主要介绍了简单了解java中int和Integer的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.Integer是int的包装类,int则是java的一种基本数据类型 2.Integer变量必须实例化(new 一下是最常见的实例化)后才能使用,而int变量不需要 3.Integer实际是对象的引用,new Integer(),实际上是生成一个指针指向此对象:而int则是直接存储数据值 4.Integer的默认值是null,in

  • 简单讲解java中throws与throw的区别

    Java中throws和throw的区别讲解 当然,你需要明白异常在Java中式以一个对象来看待. 并且所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,但是一般情况下Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行. 直接进入正题哈: 1.用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常. 1.1   throw是语句抛出一个异常. 语法:throw (异常对象);         

  • spring中REST和RESTful的区别以及基本实现

    目录 简介 REST概念: RESTful概念: RESTful实现 GET, 查询所有用户信息 GET, 根据用户ID查询用户信息 POST, 添加用户信息 PUT, 修改用户信息 简介 REST概念: REST :全称:Representational State Transfer,意思:表现层资源状态转移 详细解释可分为三部分: 资源 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成.每个资源是服务器上一个可命名的抽象概念.因为资源是一个抽象的概念,所以它不仅仅能代表服务

  • 一文搞懂Spring中@Autowired和@Resource的区别

    目录 1.来源不同 2.依赖查找顺序不同 2.1 @Autowired 查找顺序 2.2 @Resource 查找顺序 2.3 查找顺序小结 3.支持的参数不同 4.依赖注入的支持不同 5.编译器提示不同 总结 @Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解.它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同,并且这也是常见的面试题之一,所以我们今天就来盘它. @Autowired 和 @Resource 的区

随机推荐