FactoryBean 是一个特殊的 bean,为什么特殊呢?

特殊的 bean

1、FactoryBean 是一个接口,实现这个接口,可以重写 3 个方法,至少需要重写 2 个方法

  1. public interface FactoryBean<T> {
  2. @Nullable
  3. T getObject() throws Exception;
  4. @Nullable
  5. Class<?> getObjectType();
  6. default boolean isSingleton() {
  7. return true;
  8. }
  9. }

2、通过 context.getBean("factoryBean") 获取的对象,并不是 FactoryBean 本身,而是 FactoryBean 的 getObject() 返回的对象
**

获取 bean 对象

image.png

1、获取生产出的 bean 对象

如果想要获取 FactoryBean 生产出来的 bean 对象的话,直接通过 getBean 就可以获取到生产出来的对象实例
context.getBean("factoryBean") ,如返回 org.wesoft.spring.factorybean.User@23faf8f2

2、获取自身 bean 对象

如果想获取自身 bean 对象,也就是 FactoryBean 本身,那么需要在名称前面加一个 “&” **符号
context.getBean("&factoryBean") ,如返回 org.wesoft.spring.factorybean.MyFactoryBean@2d6eabae

Spring 对 FactoryBean 的判断逻辑

  1. protected String transformedBeanName(String name) {
  2. return canonicalName(BeanFactoryUtils.transformedBeanName(name));
  3. }
  4. // BeanFactoryUtils.transformedBeanName(name)
  5. public static String transformedBeanName(String name) {
  6. Assert.notNull(name, "'name' must not be null");
  7. // 检查是不是要获取 FactoryBean,即以 & 打头
  8. if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
  9. return name;
  10. }
  11. // 以 & 打头的 beanName
  12. return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
  13. do {
  14. // 截取掉 & 字符
  15. beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
  16. }
  17. while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
  18. return beanName;
  19. });
  20. }
  21. // canonicalName(BeanFactoryUtils.transformedBeanName(name))
  22. public String canonicalName(String name) {
  23. String canonicalName = name;
  24. // Handle aliasing...
  25. String resolvedName;
  26. do {
  27. // 去 aliasMap 找是否有对应的 beanName
  28. resolvedName = this.aliasMap.get(canonicalName);
  29. if (resolvedName != null) {
  30. canonicalName = resolvedName;
  31. }
  32. }
  33. while (resolvedName != null);
  34. return canonicalName;
  35. }

FactoryBean 生产的出来的单例对象,不会放到 singleObjects 中,只会放到 factoryBeanObjectsCache 中

FactoryBean 与 BeanFactory 区别

FactoryBean 是一个特殊的 bean,可以生产一些特殊(复杂)的 bean 对象,可以理解为生产一种复杂的 bean 对象的工厂

BeanFactory 是一个大容器,也可以生产 bean 对象,包括 FactoryBean 的对象,一个大容器

FactoryBean 与 @Bean 的区别

@Bean 与 FactoryBean 所想要实现的功能类似,都能自定义产生 bean 对象,但是 FactoryBean 更加容易扩展(如实现一些其他接口),而 @Bean 则不能

FactoryBean 的应用场景

当需要按一些特定条件和组合产生某些对象时,可以考虑使用 FactoryBean 来实现,典型的是案例是,MyBatis 利用 FactoryBean 来生产 Mapper 的代理对象(因为 Mapper 是一个接口)