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

一、BeanFactory

BeanFactory是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean()、containsBean()等管理Bean的通用方法。Spring的容器都是它的具体实现如:

  • DefaultListableBeanFactory
  • XmlBeanFactory
  • ApplicationContext

这些实现类又从不同的维度分别有不同的扩展。

  1. public interface BeanFactory {
  2. String FACTORY_BEAN_PREFIX = "&";
  3. Object getBean(String name) throws BeansException;
  4. <T> T getBean(String name, Class<T> requiredType) throws BeansException;
  5. Object getBean(String name, Object... args) throws BeansException;
  6. <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
  7. boolean containsBean(String name);
  8. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
  9. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
  10. boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
  11. boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
  12. @Nullable
  13. Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  14. @Nullable
  15. Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
  16. String[] getAliases(String name);
  17. }

二、FactoryBean

一般情况下,Spring通过反射机制利用beanclass属性指定实现类来实例化Bean.
在某些情况下,实例化bean过程比较复杂,如果根据传统的方式,则需要在<bean>中提供大量的配置信息,配置方式的灵活性是收到限制的,这个时候采用编码的方式可能会得到一个简单的方案
Spring为此提供了一个org.springframework.beans.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。

2.1、源码

  1. public interface FactoryBean<T> {
  2. //从工厂中获取bean
  3. @Nullable
  4. T getObject() throws Exception;
  5. //获取Bean工厂创建的对象的类型
  6. @Nullable
  7. Class<?> getObjectType();
  8. //Bean工厂创建的对象是否是单例模式
  9. default boolean isSingleton() {
  10. return true;
  11. }
  12. }

从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上’&’符号。

  • getObject(‘name’)返回工厂中的实例
  • getObject(‘&name’)返回工厂本身的实例

通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

2.2、示例

先定义一个Bean实现FactoryBean接口

  1. @Component
  2. public class MyBean implements FactoryBean {
  3. private String message;
  4. public MyBean() {
  5. this.message = "通过构造方法初始化实例";
  6. }
  7. @Override
  8. public Object getObject() throws Exception {
  9. // 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例。
  10. // 如return new Student()...
  11. return new MyBean("通过FactoryBean.getObject()创建实例");
  12. }
  13. @Override
  14. public Class<?> getObjectType() {
  15. return MyBean.class;
  16. }
  17. public String getMessage() {
  18. return message;
  19. }
  20. }

MyBean实现了FactoryBean接口的两个方法,getObject()是可以返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。然后测试代码中先通过名称获取Bean实例,打印message的内容,再通过&+名称获取实例并打印message内容。

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = TestApplication.class)
  3. public class FactoryBeanTest {
  4. @Autowired
  5. private ApplicationContext context;
  6. @Test
  7. public void test() {
  8. MyBean myBean1 = (MyBean) context.getBean("myBean");
  9. System.out.println("myBean1 = " + myBean1.getMessage());
  10. MyBean myBean2 = (MyBean) context.getBean("&myBean");
  11. System.out.println("myBean2 = " + myBean2.getMessage());
  12. System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
  13. }
  14. }
  1. myBean1 = 通过FactoryBean.getObject()初始化实例
  2. myBean2 = 通过构造方法初始化实例
  3. myBean1.equals(myBean2) = false

2.3、使用场景ProxyFactoryBean

说了这么多,为什么要有FactoryBean这个东西呢,有什么具体的作用吗?

FactoryBean在Spring中最为典型的一个应用就是用来创建AOP的代理对象

我们知道AOP实际上是Spring在运行时创建了一个代理对象,也就是说这个对象,是我们在运行时创建的,而不是一开始就定义好的,这很符合工厂方法模式。更形象地说,AOP代理对象通过Java的反射机制,在运行时创建了一个代理对象,在代理对象的目标方法中根据业务要求织入了相应的方法。这个对象在Spring中就是——ProxyFactoryBean。
所以,FactoryBean为我们实例化Bean提供了一个更为灵活的方式,我们可以通过FactoryBean创建出更为复杂的Bean实例。

三、区别

  • 他们两个都是个工厂,但FactoryBean本质上还是一个Bean,也归BeanFactory管理
  • BeanFactory是Spring容器的顶层接口,FactoryBean更类似于用户自定义的工厂接口。

ObjectFactory

  1. @FunctionalInterface
  2. public interface ObjectFactory<T> {
  3. /**
  4. * Return an instance (possibly shared or independent)
  5. * of the object managed by this factory.
  6. * @return the resulting instance
  7. * @throws BeansException in case of creation errors
  8. */
  9. T getObject() throws BeansException;
  10. }