BeanFactory和FactoryBean区别(含源码分析)
1.BeanFactory
BeanFactory是Spring中的一个接口,是一个工厂类,用于管理Bean。BeanFactory是IOC容器的核心,指责包括:实例化,配置应用程序中的对象和建立这些对象之间的依赖关系,ApplicationContext则是BeanFactory的高级版本。
XMLBeanFactory是BeanFactory的一种实现,通过读取XML元数据中的信息,来实例化Bean,交由Spring容器管理,构建一个可配置的应用。
BeaFactory中有如下方法:
boolean containsBean(String beanName)
Object getBean(String)
Object getBean(String, Class)
Class getType(String name)
boolean isSingleton(String)
String[] getAliases(String name)
可以方便地获取bean,对Bean进行操作和判断。
2.FactoryBean则是一种可以定制实例化Bean的方式,通过实现FactoryBean,完成自定义的Bean实例化细节。例如可以通过FactoryBean代理对象,对其所有方法进行拦截,形成AOP类似功能。使用FactoryBean避免了在XML文件中配置各种属性,更灵活,但是需要在FactoryBean的实现类中编码完成类的实例化方式。
FactoryBean有如下方法:
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
支持泛型,可将被实际对象传入,调用getObject方法时返回的是传入泛型的指定对象类型。
先用一个例子使用一下FactoryBean:
@Component("carFactoryBean")
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo;
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setBrand(carInfo.split(",")[0]);
car.setName(carInfo.split(",")[1]);
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
public static void main(String[] args) {
}
}
XML文件配置如下
<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="carFactoryBean" class="com.fanfte.spring.CarFactoryBean" >
<property name="carInfo" value="BMW,AAA"></property>
</bean>
</beans>
在客户端中使用:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application-test.xml");
Car o1 = context.getBean("carFactoryBean", Car.class);
Object o2 = context.getBean("&carFactoryBean");
System.out.println(o1.getClass() + " " + o1.getName());
System.out.println(o2.getClass());
}
}
实际输出
class com.fanfte.spring.Car AAA
class com.fanfte.spring.CarFactoryBean
如果getBean传入参数位bean的名称,加上"&"则会返回FactoryBean对象本身。
接下来查看一下源码看看Spring中context.getBean("carFactoryBean", Car.class);做了什么
跟踪doGetBean可以到如下方法
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 在此获取到了carFactoryBean实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 此处获取到FactoryBean中的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
在getObjectForBeanInstance中判断是否是FactoryBean对象,如果是,则通过它的getObject()获取对象方法构造对象。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 验证是否是FactoryBean对象,不是则抛出异常
// 1.bean的name如果以&开头,则是FactoryBean实例,判断是否是FactoryBean的实例
// 2.是否是FactoryBean的实例
// 如果以&开头,但不是FactoryBean实例,则抛出异常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 执行到此处,已经得到了bean,如果是普通的bean,或者是FacoryBean实例,直接返回
// 是factoryBean实例,BeanFactoryUtils.isFactoryDereference则是以是否以&开头判断的
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 如果不是以&开头的FactoryBean,从FactoryBeanObjectCache中获取由Factory创建的bean
Object object = null;
if (mbd == null) {
// 从FactoryBeanObjectCache中获取由Factory创建的bean
object = getCachedObjectForFactoryBean(beanName);
}
// 没有在cache中获取到bean
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 将FactoryBean中获取bean的工作委托给getObjectFormFactoryBean方法
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
String FACTORY_BEAN_PREFIX = "&";
// 判断bean的name是否是factoryBean,判断是否以&开头
public static boolean isFactoryDereference(String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
进入getObjectFromFactoryBean方法
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 从缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 实际获取FactoryBean
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
进入获取FactoryBean中对象的方法
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 调用carFactoryBean的getObject()方法,进行自定义实例化bean
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}
最后进入carFactoryBean的getObject()方法。
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setBrand(carInfo.split(",")[0]);
car.setName(carInfo.split(",")[1]);
return car;
}
至此,自定义通过factoryBean获取对象完成。
总结:
1.BeanFactory是Spring的工厂接口,为IOC容器的核心实现。FactoryBean提供了方法自定义实现Bean,避免了复杂的配置,可用于实现对象代理等,封装了对象创建的内部实现,并提供了获取对象的接口。