Spring IOC - FactoryBean源码解析

FactoryBean是Spring中用于自定义Bean创建的接口,它提供getObject()和getObjectType()方法。通过实现FactoryBean,可以在复杂创建逻辑或参数变化时控制Bean实例的生成。示例展示了如何创建一个简单的FactoryBean,并解释了Spring容器如何处理FactoryBean实例及其创建的对象,包括它们在容器中的存储位置。
摘要由CSDN通过智能技术生成

​​​​​1. 介绍

        FactoryBean是Spring框架中的一个接口,它允许我们自定义一个工厂类,用于创建和管理Spring容器中的Bean实例。FactoryBean接口定义了两个方法:

  • getObject():用于返回一个Bean实例,这个方法可以自定义创建Bean实例的逻辑。
  • getObjectType():用于返回创建的Bean实例的类型。

        当我们在Spring中自定义一个FactoryBean时,Spring容器会先创建这个FactoryBean实例,然后调用它的getObject()方法来获取实际的Bean实例。FactoryBean的使用场景比较广泛,例如:

  • 当我们需要创建一个Bean实例时,但是这个Bean实例的创建过程比较复杂,需要进行一些额外的逻辑处理,这时我们可以使用FactoryBean来自定义创建过程。
  • 当我们需要创建多个实例时,但是这些实例的创建逻辑比较相似,只有一些参数不同,这时我们可以使用FactoryBean来封装这些相似的逻辑,避免重复代码。

2. Demo

@Component
public class MyFactoryBean implements FactoryBean {

    @Override
    public Object getObject() throws Exception {
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

public class FactoryBeanTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(FactoryBeanTest.class.getPackage().getName());
        System.out.println(annotationConfigApplicationContext.getBean("&myFactoryBean"));
        System.out.println(annotationConfigApplicationContext.getBean("myFactoryBean"));
    }
}

        返回结果如下: 

 3. 现象

  • FactoryBean会创建两个对象
  • beanName为myFactoryBean,实例为自己本身,存储在单例池singletonObjects(一级缓存)中

  • 通过getObject创建的对象,beanName为myFactory,缓存在factoryBeanObjectCache中,它是专门用来缓存通过FactoryBean创建的单例对象的。

  • 上述两个单例池均为ConcurrentHashMap类型,属于Spring容器的一部分。

  • 单例池和factoryBeanObjectCache中的beanName都为myFactory,没有&前缀,该前缀只是决定了从哪个缓冲池取对象

4. 源码解析

注:源码较长,只关注主干逻辑,省略了非主要代码

执行路径:main#getBean -》 AbstractApplicationContext#getBean -》 AbstractBeanFactory#doGetBean -》 AbstracBeanFactory#getObjectForBeanInstance -》 FactoryBeanRegistrySupport#getObjectFromFactoryBean -》FactoryBeanRegistrySupport#doGetObjectFromFactoryBean -》 FactoryBean#getObject

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   // 如果name以一个或多个&符合开头,则去掉该一个或多个&符号,否则直接返回
   // 如果是别名,则转换成规范名称
   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   // 从单例池中获取实例,在AnnotationConfigApplicationContext实例化后,此时
   // 单例池中已有键值对:myFactoryBean:MyFactoryBean实例,所以能够获取到
   Object sharedInstance = getSingleton(beanName);
   // 接下来代码基本就是一个if-else分支
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 获取给定bean实例的对象,可以是bean实例本身,也可以是FactoryBean创建的对象
      // 下面会解析该方法
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   } else {
       // else分支在这里可以不用关注
   }
   return (T) bean;
}
protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // 如果bean实例是FactoryBean类型或者以&字符开头直接返回
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
   }

   Object object = null;
   if (mbd == null) {
      // 从factoryBeanObjectCache缓冲池中获取对象
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // Return bean instance from factory.
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // Caches object obtained from FactoryBean if it is a singleton.
      if (mbd == null && containsBeanDefinition(beanName)) {
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      // 非主逻辑代码,先忽略
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      // 通过回调FactoryBean#getObject获取对象,该方法继续调用doGetObjectFromFactoryBean
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
      throws BeanCreationException {

   Object object;
   try {
         // 回到factoryBean的getObject方法,返回的对象会缓存到factoryBeanObjectCache池子中
         object = factory.getObject();
   }
   catch (FactoryBeanNotInitializedException ex) {
      throw new BeanCurrentlyInCreationException(beanName, ex.toString());
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
   }

   // Do not accept a null value for a FactoryBean that's not fully
   // initialized yet: Many FactoryBeans just return null then.
   if (object == null) {
      if (isSingletonCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(
               beanName, "FactoryBean which is currently in creation returned null from getObject");
      }
      object = new NullBean();
   }
   return object;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值