Java Spring BeanFactory FactoryBean ObjectFactory

结论

BeanFactory就是对象工厂,用于实例化和保存对象。
FactoryBean是一个工厂对象,用于实例化创建过程比较复杂的对象。
ObjectFactory是某个特定的工厂,用于在项目启动时,延迟实例化对象,解决循环依赖问题。

BeanFactory

Spring最最核心的接口,Bean工厂,从名字上就能看出这是一个工厂。那么既然是工厂就是用来生产对象的。

FactoryBean

从名字上能看出这是一个Bean。Bean就是Spring对对象的一种定义,一个Bean就是一个或者一些同类型的对象。
FactoryBean是一个接口。

  1. public interface FactoryBean<T> {
  2. //返回的对象实例
  3. T getObject() throws Exception;
  4. //Bean的类型
  5. Class<?> getObjectType();
  6. //true是单例,false是非单例 在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
  7. boolean isSingleton();
  8. }

可以观察到FactoryBean接口有三个方法。
getObject用来返回实例化后的对象。
getObjectType用来返回对象的类型。
isSingleton用来标识对象是否为单例的,这里默认为true,Spring会将实例化后的对象放入BeanFactory容器中。
从方法上,能推测出,这个凡是实现了FactoryBean接口的类,负责返回这个java类的实例化对象。
从设计模式的角度来看这就是典型的工厂方法模式。由一个特定的工厂来生产特定的java类的实例化对象。
那么这种写法有哪些好处呢?
正常情况下,Spring中在实例化对象的时候,都是由BeanFactory从上下文中获取BeanDefinition信息,然后通过反射,调用这个java类的构造方法进行实例化。而现在这种形式,相当于将实例化的功能交给了FactoryBean去实现。这种方式主要使用在一些比较复杂的实例化过程中,并非简单地设置一些参数或者设置的参数过多,过程中可能需要做一些复杂的解析、判断和逻辑处理,这个时候交由Spring去通过反射进行实例化可能就不太灵活了,
Spring容器中有两种Bean,一种是普通的Bean对象,一种是实现了FactoryBean的工厂Bean对象。如果从BeanFactorygetBean的时候,获取到的Bean对象是工厂Bean,会自动的调用它的getObject方法返回真实实例化对象。
如果就是需要获取FactoryBean对象,需要在getBean的时候加上前缀’&’。
Spring自身就对FactoryBean有70多种实现,比较常见的就是Proxy,Jndi等场景。AOP中使用的ProxyFactoryBean
Dubbo中使用的ReferenceBean
Mybatis中使用的SqlSessionFactoryBean

ObjectFactory

  1. public interface ObjectFactory<T> {
  2. //返回的对象实例
  3. T getObject() throws BeansException;
  4. }

这用于延迟查找的场景,它就是一个普通工厂,当得到 ObjectFactory 对象时,相当于 Bean 没有被创建,只有当 getObject() 方法时,才会触发 Bean 实例化等生命周期。
主要用于暂时性地获取某个 Bean Holder 对象,如果过早的加载,可能会引起一些意外的情况,比如当 Bean A 依赖 Bean B 时,如果过早地初始化 A,那么 B 里面的状态可能是中间状态,这时候使用 A 容易导致一些错误