引言
关于FactoryBean 和 BeanFactory的对比文章比较多,但是对ObjectFactory的描述就比较少,今天我们对比下这三种的区别。
结论
BeanFactory就是对象工厂,Spring的底层容器,用于实例化和保存对象。
FactoryBean是一个工厂对象,用于实例化创建过程比较复杂的对象,对象的创建过程是由用户自己控制的。
ObjectFactory是某个特定的工厂,用于在项目启动时,延迟实例化对象,解决循环依赖问题,也就是三级缓存那里会用到,以及结合Scope,灵活方便的实现是否需要创建对象。
BeanFactory
Spring最最核心的接口,Bean工厂,从名字上就能看出这是一个工厂。它是Spring最底层的容器,负责实例化和保存Spring中的Bean。
public interface BeanFactory {
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;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
## 方法很多,不再赘述
}
FactoryBean
public interface FactoryBean<T> {
//返回的对象实例
T getObject() throws Exception;
//Bean的类型
Class<?> getObjectType();
//true是单例,false是非单例 在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
boolean isSingleton();
}
我们观察到FactoryBean接口有三个方法。
getObject
用来返回实例化后的对象。
getObjectType
用来返回对象的类型。
isSingleton
用来标识对象是否为单例的,这里默认为true,Spring会将实例化后的对象放入BeanFactory容器中。
从方法上,能推测出,这个凡是实现了FactoryBean接口的类,负责返回这个java类的实例化对象。
从设计模式的角度来看这就是典型的工厂方法模式。由一个特定的工厂来生产特定的java类的实例化对象。
那么这种写法有哪些好处呢?
正常情况下,Spring中在实例化对象的时候,都是由BeanFactory从上下文中获取BeanDefinition信息,然后通过反射,调用这个java类的构造方法进行实例化。而现在这种形式,我们相当于将实例化的功能交给了FactoryBean去实现。这种方式主要使用在一些比较复杂的实例化过程中,并非简单地设置一些参数或者设置的参数过多,过程中可能需要做一些复杂的解析、判断和逻辑处理,这个时候交由Spring去通过反射进行实例化可能就不太灵活了,
Spring容器中有两种Bean,一种是普通的Bean对象,一种是实现了FactoryBean的工厂Bean对象。如果从BeanFactory中getBean的时候,获取到的Bean对象是工厂Bean,会自动的调用它的getObject方法返回真实实例化对象。
如果就是需要获取FactoryBean对象,需要在getBean的时候加上前缀’&'。
Spring自身就对FactoryBean有70多种实现,比较常见的就是Proxy,Jndi等场景。
AOP中使用的ProxyFactoryBean。
Dubbo中使用的ReferenceBean。
Mybatis中使用的SqlSessionFactoryBean。
FactoryBean的着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的话spring会利用单例缓存来缓存通过FactoryBean创建的对象。
ObjectFactory
public interface ObjectFactory<T> {
//返回的对象实例
T getObject() throws BeansException;
}
这用于延迟查找的场景,它就是一个普通工厂,当得到 ObjectFactory 对象时,相当于 Bean 没有被创建,只有当 getObject() 方法时,才会触发 Bean 实例化等生命周期。
一方面在循环依赖的时候,用于延迟初始化,见org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
中调用addSingletonFactory
方法,会把ObjectFactory的Lambda表达式放入三级缓存。
另一方面,在AbstractBeanFacotry在doGetBean处的使用时,将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope。除此之外ObjectFactory就是一个普通的接口
简单来说就是通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机也可以用来延迟初始化来解决循环依赖问题。