FactoryBean 是一个特殊的 bean,为什么特殊呢?
特殊的 bean
1、FactoryBean 是一个接口,实现这个接口,可以重写 3 个方法,至少需要重写 2 个方法
public interface FactoryBean<T> {@NullableT getObject() throws Exception;@NullableClass<?> getObjectType();default boolean isSingleton() {return true;}}
2、通过 context.getBean("factoryBean") 获取的对象,并不是 FactoryBean 本身,而是 FactoryBean 的 getObject() 返回的对象
**
获取 bean 对象

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 的判断逻辑
protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));}// BeanFactoryUtils.transformedBeanName(name)public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");// 检查是不是要获取 FactoryBean,即以 & 打头if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}// 以 & 打头的 beanNamereturn transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {// 截取掉 & 字符beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});}// canonicalName(BeanFactoryUtils.transformedBeanName(name))public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {// 去 aliasMap 找是否有对应的 beanNameresolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}
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 是一个接口)
