Spring的BeanFactory和FactoryBean
官方定义
- BeanFactory:Spring Bean容器的根接口
- FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例。
源码解析
BeanFactory
public interface BeanFactory {
//标注是获取FactoryBean的实现类,而不是调用getObject()获取的实例
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;
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作为bean的容器管理器,提供了一系列获取bean以及获取bean属性的方法。
写一个小例子试验下:
SimpleBean:
public class SimpleBean {
public void send() {
System.out.println("Hello Spring Bean!");
}
}
Spring配置文件config.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="simpleBean" class="base.SimpleBeanFactoryBean"/>
</beans>
测试方法:
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
BeanFactory beanFactory = context.getAutowireCapableBeanFactory();
System.out.println("通过名称获取bean");
SimpleBean simpleBean = (SimpleBean) beanFactory.getBean("simpleBean");
simpleBean.send();
System.out.println("通过名称和类型获取bean");
simpleBean = beanFactory.getBean("simpleBean", SimpleBean.class);
simpleBean.send();
System.out.println("通过类型获取bean");
simpleBean = beanFactory.getBean(SimpleBean.class);
simpleBean.send();
boolean containsBean = beanFactory.containsBean("simpleBean");
System.out.println("是否包含 simpleBean ? " + containsBean);
boolean singleton = beanFactory.isSingleton("simpleBean");
System.out.println("是否是单例? " + singleton);
boolean match = beanFactory.isTypeMatch("simpleBean", ResolvableType.forClass(SimpleBean.class));
System.out.println("是否是SimpleBean类型 ? " + match);
match = beanFactory.isTypeMatch("simpleBean", SimpleBean.class);
System.out.println("是否是SimpleBean类型 ? " + match);
Class<?> aClass = beanFactory.getType("simpleBean");
System.out.println("simpleBean 的类型是 " + aClass.getName());
String[] aliases = beanFactory.getAliases("simpleBean");
System.out.println("simpleBean 的别名 : " + Arrays.toString(aliases));
}
控制台结果:
通过名称获取bean
Hello Spring Bean!
通过名称和类型获取bean
Hello Spring Bean!
通过类型获取bean
Hello Spring Bean!
是否包含 simpleBean ? true
是否是单例? true
是否是SimpleBean类型 ? true
是否是SimpleBean类型 ? true
simpleBean 的类型是 base.SimpleBean
simpleBean 的别名 : []
FactoryBean
public interface FactoryBean<T> {
/**
* 获取一个bean,如果配置了工厂bean,在getBean的时候,将会调用此方法,获取一个bean
*/
T getObject() throws Exception;
/**
* 获取bean的类型
*/
Class<?> getObjectType();
/**
* 是否是单例
*/
boolean isSingleton();
}
接口是泛型,定义了三个方法,其中getObject()是工厂模式的体现,将会通过此方法返回一个bean的实例。
一个小例子:
public class SimpleBeanFactoryBean implements FactoryBean<SimpleBean> {
@Override
public SimpleBean getObject() throws Exception {
System.out.println("MyFactoryBean getObject");
return new SimpleBean();
}
@Override
public Class<?> getObjectType() {
System.out.println("MyFactoryBean getObjectType");
return SimpleBean.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
以上可以修改为单例模式,可以做成线程安全的单例,可塑性较高。
配置文件config.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="simple" class="base.SimpleBeanFactoryBean"/>
</beans>
注意,我们在这里只配置了SimpleBeanFactoryBean,并没有配置SimpleBean,接下来看下getBean方法的输出。
ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
SimpleBean simpleBean = context.getBean(SimpleBean.class);
simpleBean.send();
控制台输出:
MyFactoryBean getObjectType
MyFactoryBean getObject
Hello Spring Bean!
由此我们可以看出FactoryBean的执行流程
- 通过
getObjectType获取bean的类型 - 调用
getObject方法获取bean的实例
总结
BeanFactory和FactoryBean其实没有关系,只是名称比较像而已。
BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。
Spring的BeanFactory和FactoryBean的更多相关文章
- Spring中BeanFactory与FactoryBean的区别
在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混. 一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层 ...
- 【Java面试】Spring中 BeanFactory和FactoryBean的区别
一个工作了六年多的粉丝,胸有成竹的去京东面试. 然后被Spring里面的一个问题卡住,唉,我和他说,6年啦,Spring都没搞明白? 那怎么去让面试官给你通过呢? 这个问题是: Spring中Bean ...
- Spring中BeanFactory与FactoryBean到底有什么区别?
一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean().containsBean()等管理Bea ...
- Spring之BeanFactory和FactoryBean接口的区别
目录 一.BeanFactory接口 二.FactoryBean接口 1.简单实现 2.增强实现 3.FactoryBean的实际使用案例 三.总结 @ Spring框架中的BeanFactory ...
- spring中BeanFactory和FactoryBean的区别
共同点: 都是接口 区别: BeanFactory 以Factory结尾,表示它是一个工厂类,用于管理Bean的一个工厂 在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器 ...
- BeanFactory 和FactoryBean的区别
转自:https://www.cnblogs.com/aspirant/p/9082858.html BeanFacotry是spring中比较原始的Factory.如XMLBeanFactory就是 ...
- 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 ...
- Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于 ...
- Spring BeanFactory 与 FactoryBean 的区别
BeanFactory 和 FactoryBean 都是Spring Beans模块下的接口 BeanFactory是spring简单工厂模式的接口类,spring IOC特性核心类,提供从工厂类中获 ...
随机推荐
- Leetcode 题目整理-5 Valid Parentheses & Merge Two Sorted Lists
20. Valid Parentheses Given a string containing just the characters '(', ')', '{', '}', '[' and ']', ...
- parzen 窗的matlab实现
用一下程序简单实现使用parzen窗对正态分布的概率密度估计: (其中核函数选用高斯核) %run for parzen close all;clear all;clc; x=normrnd(0,1, ...
- 按照相应的格式获取系统时间并将其转化为SQL中匹配的(date)时间格式
在获取时间时需要对时间格式进行设置,此时就需要用到SimpleDateFormat 类 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM ...
- html网页压缩保存到数据库,减少空间占用,实现过程遇到的解压问题
场景: python获取到网页,把网页gzip打包,并Base64编码保存: 由java负责Base64解码并解压二进制成html 遇到的问题: 1.python 的request,缺省就把gzip响 ...
- 创建一个圆类Circle的对象,分别设置圆的半径计算并分别显示圆半径、圆面积、圆周长。
编写一个圆类Circle,该类拥有: ①一个成员变量 Radius(私有,浮点型): // 存放圆的半径: ②两个构造方法 Circle( ) // 将半径设为0 Circle(double r ) ...
- JSP&Servlet学习笔记----第1/2章
HTML(HyperText Markup Language):超文本标记语言 HTTP(HyperText Transfer Protocol):超文本传输协议 URL(Uniform Resour ...
- 机器学习(ML)十二之编码解码器、束搜索与注意力机制
编码器—解码器(seq2seq) 在自然语言处理的很多应用中,输入和输出都可以是不定长序列.以机器翻译为例,输入可以是一段不定长的英语文本序列,输出可以是一段不定长的法语文本序列,例如 英语输入:“T ...
- Go语言实现:【剑指offer】旋转数组的最小数字
该题目来源于牛客网<剑指offer>专题. 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3, ...
- Bound Method and Unbound Method - 绑定方法 与 非绑定方法
Bound Method and Unbound Method 通常有两种方法对类的方法(instance.method)/属性(class.attribute)进行引用, 一种称做 Bound Me ...
- Linux中查看日志文件的正确姿势,求你别tail走天下了!
作为一个后端开发工程师,在Linux中查看查看文件内容是基本操作了.尤其是通常要分析日志文件排查问题,那么我们应该如何正确打开日志文件呢?对于笔者这种小菜鸡来说,第一反应就是 cat,tail,vi( ...