简单了解Spring中BeanFactory与FactoryBean的区别
这篇文章主要介绍了简单了解Spring中BeanFactory与FactoryBean的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混。
一、BeanFactory
BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean()、containsBean()等管理Bean的通用方法。Spring的容器都是它的具体实现如:
- DefaultListableBeanFactory
- XmlBeanFactory
- ApplicationContext
这些实现类又从不同的维度分别有不同的扩展。
1.1BenaFactory源码
publicinterfaceBeanFactory{
/**
*用来获得实例的引用,并且区分FactoryBean区分。
*如果使用bean的名字myJndiObject获取FactoryBean,返回的是一个工厂,而不是工厂的实例;如果需要获得工厂实例,需要转义。
*/
StringFACTORY_BEAN_PREFIX="&";
/**
*根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.
*/
ObjectgetBean(Stringname)throwsBeansException;
/**
*根据bean的名称,获取指定的bean实例,该实例可以是共享的,也可以是独立的.并且增加了一个类型的检验。
*/
TgetBean(Stringname,ClassrequiredType)throwsBeansException;
ObjectgetBean(Stringname,Object...args)throwsBeansException;
/**
*根据给定类型返回匹配的bean实例.
*/
TgetBean(ClassrequiredType)throwsBeansException;
TgetBean(ClassrequiredType,Object...args)throwsBeansException;
/**
*检查spring的bean容器中是否包含有该bean
*/
booleancontainsBean(Stringname);
/**
*判断bean的作用域是否是singleton
*/
booleanisSingleton(Stringname)throwsNoSuchBeanDefinitionException;
/**
*判断bena的作用域是否是prototype
*/
booleanisPrototype(Stringname)throwsNoSuchBeanDefinitionException;
/**
*检查给定名称的bean是否和指定类型匹配.更确却的说是通过检查给定的bean,返回指定类型的目标对象
*/
booleanisTypeMatch(Stringname,ResolvableTypetypeToMatch)throwsNoSuchBeanDefinitionException;
booleanisTypeMatch(Stringname,Class>typeToMatch)throwsNoSuchBeanDefinitionException;
/**
*获取给定名称的bean的class类型
*/
Class>getType(Stringname)throwsNoSuchBeanDefinitionException;
/**
*获取给定bean名称的别名,如果根据别名检索,将会获得原始bean名称。
*
String[]getAliases(Stringname);
}
1.2使用场景
- 从Ioc容器中获取Bean(byNameorbyType):context.getBean("father",Father.class)、context.getBean("father")
- 检索Ioc容器中是否包含指定的Bean:context.containsBean("father")
- 判断Bean是否为单例:context.isSingleton("father")
二、FactoryBean
首先它是一个Bean,但又不仅仅是一个Bean。它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。
2.1FactoryBean源码
publicinterfaceFactoryBean{ /** *从工厂中获取bean实例 */ TgetObject()throwsException; /** *从工厂中获取bean实例对象的类型 */ Class>getObjectType(); /** *工厂创建的对象是否是单例 */ booleanisSingleton(); }
从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。即一个BeanA如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上'&'符号。
- getObject('name')返回工厂中的实例
- getObject('&name')返回工厂本身的实例
通常情况下,bean无须自己实现工厂模式,Spring容器担任了工厂的角色;但少数情况下,容器中的bean本身就是工厂,作用是产生其他bean实例。由工厂bean产生的其他bean实例,不再由Spring容器产生,因此与普通bean的配置不同,不再需要提供class元素。
2.2示例
先定义一个Bean实现FactoryBean接口:
@Component
publicclassMyBeanimplementsFactoryBean{
privateStringmessage;
publicMyBean(){
this.message="通过构造方法初始化实例";
}
publicMyBean(Stringmessage){
this.message=message;
}
@Override
publicObjectgetObject()throwsException{
//这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例
returnnewMyBean("通过FactoryBean.getObject()创建实例");
}
@Override
publicClass>getObjectType(){
returnMyBean.class;
}
publicStringgetMessage(){
returnmessage;
}
@Override
publicbooleanisSingleton(){
returnfalse;
}
}
MyBean实现了FactoryBean接口的三个方法,getObject()是可以返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。然后测试代码中先通过名称获取Bean实例,打印message的内容,再通过&+名称获取实例并打印message内容。
@RunWith(SpringRunner.class)
@SpringBootTest(classes=HelloApplication.class)
publicclassFactoryBeanTest{
@Autowired
privateApplicationContextcontext;
@Test
publicvoidtest(){
MyBeanmyBean1=(MyBean)context.getBean("myBean");//返回工厂中的实例,调用FactoryBean.getObject()创建实例
System.out.println("myBean1="+myBean1.getMessage());
MyBeanmyBean2=(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更类似于用户自定义的工厂接口。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。