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特性核心类,提供从工厂类中获 ...
随机推荐
- 工作流Activity框架入门(一)
Activity工作流入门 1. 工作流概念 工作流(Workflow),就是"业务过程的部分或整体在计算机应用环境下的自动化",它主要解决的是"使在多个参与者之间按照某 ...
- 8.HanLP实现--命名实体识别
笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 8. 命名实体识别 8.1 概述 命名实体 文本中有一些描述实体的词汇.比如人名. ...
- CSS颜色表示的几种方式
在CSS中颜色有很多表示方式,今天列出一些常见的颜色表示方式及它们的用法. ①color:blue; 第一种,调用颜色属性,将颜色的英文输入在冒号后,以分号结束. 这种方法直接了当,但是能表示的颜色 ...
- WeChall_Prime Factory (Training, Math)
Your task is simple:Find the first two primes above 1 million, whose separate digit sums are also pr ...
- 微信小程序—Flex布局
参考教程:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html https://xluos.github.io/demo/flexb ...
- ARTS Week 2
Nov 4,2019 ~ Nov 10,2019 Algorithm 本周主要的算法是如何求两个数的最大公因数.传统的想法便是对这两个数分解质因数,而后找到其公共因数,再相乘,这样就会得到最大公因数了 ...
- 《Python学习手册 第五版》 -第3章 你应如何运行Python程序
在这里,运行Python程序的前提是你的电脑已经配置Python相关的运行环境,如何配置可以通过本书的附件查看,也可以自行通过网络查询配置,在此不再赘述 运行一个Python程序,主要有6种方式 1. ...
- 清晰架构(Clean Architecture)的Go微服务
我用Go和gRPC创建了一个微服务项目,并试图找出最好的程序结构,它可以作为我其他项目的模板.我还将程序设计和编程的最佳实践应用于Go Microservice程序,例如清晰架构(Clean Arch ...
- mongodb 配置文件解释(转)
Mongodb 3.x配置说明,本文内容忽略了Enterprise版和一些不常用的配置. 一.配置说明 在Mongod安装包中,包含2个进程启动文件:mongod和mongos:其中mongd是核心基 ...
- SpringBoot、Spring MVC报错:Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
出现问题的原因: jdbc配置不正确 解决方案: 1.检查是否已添加数据库驱动jar包 2.检查数据库服务是否启动 3.检查数据库配置文件 主要为:dialect,driver_class,url,u ...