一直以来,很多人对于Spring中的BeanFactory和FactoryBean都是分不清楚的

BeanFactory

这个其实是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,比如我们常用到的getBean方法等

The root interface for accessing a Spring bean container. This is the basic client view of a bean container;

定义方法:

  • getBean(String name): Spring容器中获取对应Bean对象的方法,如存在,则返回该对象
  • containsBean(String name):Spring容器中是否存在该对象
  • isSingleton(String name):通过beanName是否为单例对象
  • isPrototype(String name):判断bean对象是否为多例对象
  • isTypeMatch(String name, ResolvableType typeToMatch):判断name值获取出来的bean与typeToMath是否匹配
  • getType(String name):获取Bean的Class类型
  • getAliases(String name):获取name所对应的所有的别名

主要的实现类(包括抽象类):

  • AbstractBeanFactory:抽象Bean工厂,绝大部分的实现类,都是继承于他
  • DefaultListableBeanFactory:Spring默认的工厂类
  • XmlBeanFactory:前期使用XML配置用的比较多的时候用的Bean工厂
  • AbstractXmlApplicationContext:抽象应用容器上下文对象
  • ClassPathXmlApplicationContext:XML解析上下文对象,用户创建Bean对象我们早期写Spring的时候用的就是他

使用方式:

  1. 使用ClassPathXmlApplicationContext读取对应的xml文件实例对应上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
BeanFactory factory = (BeanFactory) context;

FactoryBean

该类是SpringIOC容器是创建Bean的一种形式,这种方式创建Bean会有加成方式,融合了简单的工厂设计模式于装饰器模式

* Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.

有些人就要问了,我直接使用Spring默认方式创建Bean不香么,为啥还要用FactoryBean做啥,在某些情况下,对于实例Bean对象比较复杂的情况下,使用传统方式创建bean会比较复杂,例如(使用xml配置),这样就出现了FactoryBean接口,可以让用户通过实现该接口来自定义该Bean接口的实例化过程。即包装一层,将复杂的初始化过程包装,让调用者无需关系具体实现细节。

方法:

  • T getObject():返回实例

  • Class<?> getObjectType();:返回该装饰对象的Bean的类型

  • default boolean isSingleton():Bean是否为单例

常用类

  • ProxyFactoryBean :Aop代理Bean
  • GsonFactoryBean:Gson

使用

  1. Spring XML方式

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="demo" class="cn.lonecloud.spring.example.bo.Person">
<property name="age" value="10"/>
<property name="name" value="xiaoMing"/>
</bean> <bean id="demoFromFactory" class="cn.lonecloud.spring.example.bean.PersonFactoryBean">
<property name="initStr" value="10,init from factory"/>
</bean>
</beans>

personFactoryBean.java

package cn.lonecloud.spring.example.bean;

import cn.lonecloud.spring.example.bo.Person;
import org.springframework.beans.factory.FactoryBean; import java.util.Objects; /**
* TODO
*
* @author lonecloud <lonecloud@aliyun.com>
* @date 2020/8/4 23:39
* @since v1.0
*/
public class PersonFactoryBean implements FactoryBean<Person> { /**
* 初始化Str
*/
private String initStr; @Override
public Person getObject() throws Exception {
//这里我需要获取对应参数
Objects.requireNonNull(initStr);
String[] split = initStr.split(",");
Person p=new Person();
p.setAge(Integer.parseInt(split[0]));
p.setName(split[1]);
//这里可能需要还要有其他复杂事情需要处理
return p;
} @Override
public Class<?> getObjectType() {
return Person.class;
} public String getInitStr() {
return initStr;
} public void setInitStr(String initStr) {
this.initStr = initStr;
}
}

main方法

package cn.lonecloud.spring.example.factory;

import cn.lonecloud.spring.example.bo.Person;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* BeanFactory 例子
*
* @author lonecloud <lonecloud@aliyun.com>
* @date 2020/8/4 23:32
* @since v1.0
*/
public class SpringBeanFactoryMain { public static void main(String[] args) {
//这个是BeanFactory
BeanFactory beanFactory = new ClassPathXmlApplicationContext("application.xml");
//获取对应的对象化
Object demo = beanFactory.getBean("demo");
System.out.println(demo instanceof Person);
System.out.println(demo);
//获取从工厂Bean中获取对象
Person demoFromFactory = beanFactory.getBean("demoFromFactory", Person.class);
System.out.println(demoFromFactory);
//获取对应的personFactory
Object bean = beanFactory.getBean("&demoFromFactory");
System.out.println(bean instanceof PersonFactoryBean);
PersonFactoryBean factoryBean=(PersonFactoryBean) bean;
System.out.println("初始化参数为:"+factoryBean.getInitStr());
}
}

输出

true
Person{name='xiaoMing', age=10}
Person{name='init from factory', age=10}
true
初始化参数为:10,init from factory

区别

  1. BeanFactory:负责生产和管理Bean的一个工厂接口,提供一个Spring Ioc容器规范,
  2. FactoryBean: 一种Bean创建的一种方式,对Bean的一种扩展。对于复杂的Bean对象初始化创建使用其可封装对象的创建细节。

代码:GitHub地址

一文读懂BeanFactory和FactoryBean区别的更多相关文章

  1. 一文读懂高性能网络编程中的I/O模型

    1.前言 随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力.本文(和下篇<高性能网络编程(六):一文读懂高性能网络编程中的线程模型>)旨在为大家提供有用的 ...

  2. 即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

    本文引用了“蔷薇Nina”的“Nginx 相关介绍(Nginx是什么?能干嘛?)”一文部分内容,感谢作者的无私分享. 1.引言   Nginx(及其衍生产品)是目前被大量使用的服务端反向代理和负载均衡 ...

  3. kubernetes基础——一文读懂k8s

    容器 容器与虚拟机对比图(左边为容器.右边为虚拟机)   容器技术是虚拟化技术的一种,以Docker为例,Docker利用Linux的LXC(LinuX Containers)技术.CGroup(Co ...

  4. 一文读懂对抗生成学习(Generative Adversarial Nets)[GAN]

    一文读懂对抗生成学习(Generative Adversarial Nets)[GAN] 0x00 推荐论文 https://arxiv.org/pdf/1406.2661.pdf 0x01什么是ga ...

  5. 一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: 一文学会MySQL的explain工具 一文读懂MySQL的索引结构及查询优化 (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论不一定适用于其他版本) 就软件开 ...

  6. 一文读懂Java动态代理

    作者 :潘潘 日期 :2020-11-22 事实上,对于很多Java编程人员来说,可能只需要达到从入门到上手的编程水准,就能很好的完成大部分研发工作.除非自己强主动获取,或者工作倒逼你学习,否则我们好 ...

  7. Java8 函数式【1】:一文读懂逆变

    Java8 函数式[1]:一文读懂逆变 禁止转载 pure function 协变 逆变 Java8 引入了函数式接口,从此方法传参可以传递函数了,有人说: 不就是传一个方法吗,语法糖! lambda ...

  8. 一文读懂HTTP/2及HTTP/3特性

    摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...

  9. 一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现

    一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现 导读:近日,马云.马化腾.李彦宏等互联网大佬纷纷亮相2018世界人工智能大会,并登台演讲.关于人工智能的现状与未来,他们提出了各自的观点,也引 ...

随机推荐

  1. Redis服务之常用配置(一)

    上一篇博客聊了下redis的简介以及redis的yum安装和源码编译安装需要注意到问题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13378138.html ...

  2. 【前端】H5,底边按钮吸边,但是覆盖了列表循环的内容

    我的说情况大致类似于: PS:因为底边那个模块 绝对是浮动的,所有会遮住列表最下面一条现实的一部分, 解决:这个时候把body的底边的内边距调整到可显示的就可以了: body { background ...

  3. PHP date_create() 函数

    ------------恢复内容开始------------ 实例 返回一个新的 DateTime 对象,然后格式化日期: <?php$date=date_create("2013-0 ...

  4. 5.13 省选模拟赛 优雅的绽放吧,墨染樱花 多项式 prufer序列 计数 dp

    LINK:优雅的绽放吧,墨染樱花 当时考完只会50分的做法 最近做了某道题受到启发 故会做这道题目了.(末尾附30分 50分 100分code 看到度数容易想到prufer序列 考虑dp统计方案数. ...

  5. Java8的@sun.misc.Contended注解

    @sun.misc.Contended 介绍 @sun.misc.Contended 是 Java 8 新增的一个注解,对某字段加上该注解则表示该字段会单独占用一个缓存行(Cache Line). 这 ...

  6. day13. 迭代器与高阶函数

    一.迭代器 """ 能被next调用,并不断返回下一个值的对象,叫做迭代器(对象) 概念: 迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果 ...

  7. js数组中如何去除重复值?

    在日常开发中,我们可能会遇到将一个数组中里面的重复值去除,那么,我就将我自己所学习到的几种方法分享出来 去除数组重复值方法: 1,利用indexOf()方法去除 思路:创建一个新数组,然后循环要去重的 ...

  8. 华为云GaussDB(DWS)内存知识点,你知道吗?

    前言 在日常数据库的使用中,难免会遇到一些内存问题.此次博文主要向大家分享一些华为云数仓GaussDB(DWS)内存的基本框架以及基本视图的使用,以便遇到内存问题后可以有一个基本的判断. 注意,本篇博 ...

  9. SpringMVC入门和常用注解

    SpringMVC的基本概念 关于 三层架构和 和 MVC 三层架构 我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就 是浏览器服务器.在 ...

  10. JavaScript的continue、break和return的区别

    1. continue.break和return的区别 循环遍历. for(let i = 0; i < 5; i++){ console.log(i); // 0 1 2 3 4 } 使用co ...