BeanFactory与FactoryBean的区别
BeanFactory
是Spring容器的顶级接⼝,给具体的IOC容器的实现提供了规范。
FactoryBean
也是接⼝,为IOC容器中Bean的实现提供了更加灵活的⽅式,FactoryBean
在IOC容器的基础上给Bean的实现加上了⼀个简单⼯⼚模式和装饰模式,可以在getObject()
⽅法中灵活配置。其实在Spring源码中有很多FactoryBean
的实现类。
区别:BeanFactory
是个Factory,也就是IOC容器或对象⼯⼚,是对IOC容器的规范,FactoryBean
是特殊的Bean,一种Bean创建的方式,对Bean的一种扩展对于复杂Bean对象初始化创建使用其可封装对象的创建细节。在Spring中,所有的Bean都是由BeanFactory
(也就是IOC容器)来进⾏管理的。
BeanFactory
BeanFactory
,以Factory结尾,表示它是⼀个⼯⼚类(接⼝), 它负责⽣产和管理bean的⼀个⼯⼚。在Spring中,BeanFactory
是IOC容器的核⼼接⼝,它的职责包括:实例化、定位、配置应⽤程序中的对象及建⽴这些对象间的依赖。
BeanFactory
只是个接⼝,并不是IOC容器的具体实现,而Spring容器给出了很多种实现,如DefaultListableBeanFactory
、XmlBeanFactory
、ApplicationContext
等,其中XmlBeanFactory
就是常⽤的⼀个,该实现将以XML⽅式描述组成应⽤的对象及对象间的依赖关系。XmlBeanFactory
类将持有此XML配置元数据,并⽤它来构建⼀个完全可配置的系统或应⽤。
BeanFactory
和ApplicationContext
就是spring框架的两个IOC容器,现在⼀般使⽤ApplicationContext
,其不但包含了BeanFactory
的作⽤,同时还进⾏更多的扩展。
BeanFactory
是spring中⽐较原始的Factory。如XMLBeanFactory
就是⼀种典型的BeanFactory。
原始的BeanFactory
⽆法⽀持spring的许多插件,如AOP功能、Web应⽤等。ApplicationContext
接⼝, 它由BeanFactory
接⼝派⽣⽽来,包含BeanFactory
的所有功能,通常建议比BeanFactory
优先。
ApplicationContext
以⼀种更向⾯向框架的⽅式⼯作以及对上下⽂进⾏分层和实现继承,ApplicationContext
包还提供了以下的功能:
- MessageSource, 提供国际化的消息访问
- 资源访问,如URL和⽂件
- 事件传播
- 载⼊多个(有继承关系)上下⽂ ,使得每⼀个上下⽂都专注于⼀个特定的层次,⽐如应⽤的web层;
BeanFactory
提供的⽅法及其简单,仅提供了六种⽅法供开发者使用:
boolean containsBean(String beanName)
判断⼯⼚中是否包含给定名称的bean定义,若有则返回trueObject getBean(String)
返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回⼀个共享实例,否则将返回⼀个新建的实例,如果没有找到指定bean,该⽅法可能会抛出异常Object getBean(String, Class)
返回以给定名称注册的bean实例,并转换为给定class类型Class getType(String name)
返回给定名称的bean的Class,如果没有找到指定的bean实例,则抛出NoSuchBeanDefinitionException
异常boolean isSingleton(String)
判断给定名称的bean定义是否为单例模式String[] getAliases(String name)
返回给定bean名称的所有别名
主要的实现类
AbstractBeanFactory
:抽象bean工厂,大部分的实现类都是继承它的DefaultListableBeanFactory
:Spring默认的工厂XmlBeanFactory
:解析XML配置的bean工厂类AbstractXmlApplicationContext
:抽象应用容器上下文ClassPathXmlApplicationContext
:XML解析上下文对象,开发者创建Bean对象用(早期用得多)
// ClassPathXmlApplicationContext 使用
AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml");
LifeBean life = container.getBean("life_prototype", LifeBean.class);
FactoryBean
⼀般情况下,Spring通过反射机制利⽤<bean>
的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程⽐较复杂,如果按照传统的⽅式,则需要在<bean>
中提供⼤量的配置信息。配置⽅式的灵活性是受限的,这时采⽤编码的⽅式可能会得到⼀个简单的解决⽅案。
Spring为此提供了⼀个org.springframework.bean.factory.FactoryBean
的⼯⼚类接⼝,⽤户可以通过实现该接⼝定制实例化Bean的逻辑。FactoryBean接⼝对于Spring框架来说占⽤重要的地位,Spring⾃身就提供了70多个FactoryBean
的实现。它们隐藏了实例化⼀些复杂Bean的细节,给上层应⽤带来了便利。
从Spring3.0开始,FactoryBean
开始⽀持泛型,即接⼝声明改为FactoryBean<T>
的形式以Bean结尾,表示它是⼀个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>
接⼝的Bean,根据该Bean的ID从BeanFactory
中获取的实际上是FactoryBean的getObject()
返回的对象,⽽不是FactoryBean
本身,如果要获取FactoryBean对象,请在id
前⾯加⼀个&
符号来获取,像这样getBean(&BeanName)
。
例如⾃⼰实现⼀个FactoryBean
,功能:⽤来代理⼀个对象,对该对象的所有⽅法做⼀个拦截,在调⽤前后都输出⼀⾏LOG,模仿ProxyFactoryBean
的功能。
package org.springframework.beans.factory;
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
该接口定义了以下3个方法:
T getObject()
:返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中;boolean isSingleton()
:返回由FactoryBean创建的Bean实例的作⽤域是singleton还是prototype;Class<?> getObjectType()
:返回FactoryBean创建的Bean类型。
当配置⽂件中<bean>
的class属性配置的实现类是FactoryBean
时,通过getBean()
⽅法返回的不是FactoryBean
本身,⽽是FactoryBean#getObject()
⽅法所返回的对象,相当于FactoryBean#getObject()
代理了getBean()
⽅法。
常用类
- ProxyFactoryBean:Aop代理Bean
- GsonFactoryBean:Gson
使用案例
bean配置文件life.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">
<!-- BeanFactory and FactoryBean -->
<bean id="life" class="org.lgq.spring.LifeBean">
<property name="name" value="lgq"/>
</bean>
<bean id="lifeFromFactory" class="org.lgq.spring.LifeFactoryBean">
<property name="initStr" value="enhanced lgq"/>
</bean>
</beans>
LifeBean
代码
public class LifeBean {
private String name;
public LifeBean() {
System.out.println("LifeBean构造函数");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("LifeBean{");
sb.append("name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
public void init() {
System.out.println("this is init of LifeBean:");
}
public void destroy() {
System.out.println("this is destroy of LifeBean:" + this);
}
}
LifeFactoryBean
代码
public class LifeFactoryBean implements FactoryBean<LifeBean> {
/**
* 初始化str
*/
private String initStr;
public String getInitStr() {
return initStr;
}
public void setInitStr(String initStr) {
this.initStr = initStr;
}
@Override
public LifeBean getObject() throws Exception {
LifeBean lifeBean = new LifeBean();
lifeBean.setName(initStr);
// 这里可以对创建的bean做更多的操作
return lifeBean;
}
@Override
public Class<?> getObjectType() {
return LifeBean.class;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("LifeFactoryBean{");
sb.append("initStr='").append(initStr).append('\'');
sb.append('}');
return sb.toString();
}
}
测试代码
public class LifeTest {
@Test
public void testLife() {
// BeanFactory
BeanFactory container = new ClassPathXmlApplicationContext("life.xml");
// 获取life对象
LifeBean life = container.getBean("life", LifeBean.class);
System.out.println(life);
// 通过factoryBean获取
LifeBean lifeFromFactory = container.getBean("lifeFromFactory", LifeBean.class);
System.out.println(lifeFromFactory);
// 获取lifeFactoryBean
Object bean = container.getBean("&lifeFromFactory");
System.out.println(bean instanceof LifeFactoryBean);
LifeFactoryBean factoryBean = (LifeFactoryBean) bean;
System.out.println("初始化字符串:" + factoryBean.getInitStr());
}
}
输入结果
LifeBean{name='lgq'}
LifeBean{name='enhanced lgq'}
true
初始化字符串:enhanced lgq
总结
BeanFactory
是个Factory,也就是IOC容器或对象⼯⼚,FactoryBean
是个Bean。在Spring中,所有的Bean都是由BeanFactory
(也就是IOC容器)来进⾏管理的。但对FactoryBean
⽽⾔,这个Bean不是简单的Bean,⽽是⼀个能⽣产或者修饰对象⽣成的⼯⼚Bean,它的实现与设计模式中的⼯⼚模式和修饰器模式类似。