Spring中BeanFactory FactoryBean和ObjectFactory的三种的区别
引言
关于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你可以控制对象的创建时机也可以用来延迟初始化来解决循环依赖问题。
参考
BeanFactory和FactoryBean对比
补充介绍spring中关于FactoryBean 和 ObjectFactory的认识和区别
FactoryBean:
这个接口使你可以提供一个复杂的逻辑来生成 Bean。它本质是一个 Bean,但这个 Bean 不是用来注 入到其它地方像 Service、Dao 一样使用的,它是用来生成其它 Bean 使用的。实现了这个接口后, Spring 在容器初始化时,把实现这个接口的 Bean 取出来,使用接口的 getObject()方法来生成我们 要想的 Bean。当然,那些生成 Bean 的业务逻辑也要写 getObject()方法中。 其返回的对象不是指定类的一个实例,其返回的是该工厂 Bean 的 getObject 方法所返回的对象。创 建出来的对象是否属于单例由 isSingleton 中的返回决定。
使用场景:
1、通过外部对类是否是单例进行控制,该类自己无法感知
2、在创建 Object 对象之前进 行初始化的操作,在 afterPropertiesSet()中完成。(一次性的初始化,保存在成员变量中,并不是 每次 getObject 都会调用 afterPropertiesSet,afterPropertiesSet 只会被调用一次)
ObjectFactory:
它的目的也是作为一个工厂,来生成 Object(这个接口只有一个方法 getObject())。这个接口一般被 用来,包装一个 factory,通过个这工厂来返回一个新实例(prototype 类型)。这个接口和 FactoryBean 有点像,但 FactoryBean 的实现是被当做一个 SPI(Service Provider Interface)实例来使用在 BeanFactory 里面;ObjectFactory 的实现一般被用来注入到其它 Bean 中,作为 API 来使用。就像ObjectFactoryCreatingFactoryBean 的 例 子 , 它 的 返 回 值 就 是 一 个 ObjectFactory , 这 个 ObjectFactory 被注入到了 Bean 中,在 Bean 通过这个接口的实例,来取得我们想要的 Bean。
总的来说,FactoryBean 和 ObjectFactory 都是用来取得 Bean,但使用的方法和地方不同, FactoryBean 被配置好后,Spring 调用 getObject()方法来取得 Bean,ObjectFactory 配置好后, 在 Bean 里面可以取得 ObjectFactory 实例,需要我们手动来调用 getObject()来取得 Bean。
到此这篇关于Spring中BeanFactory FactoryBean和ObjectFactory的三种的区别的文章就介绍到这了,更多相关BeanFactory FactoryBean和ObjectFactory区别内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!