Spring源码之FactoryBeanRegistrySupport解读

首先我们可以看到FactoryBeanRegistrySupport其只有一个全局变量:

   

factoryBeanObjectCache:

然后这个类会牵扯到一个接口FactoryBean,即工厂Bean:

先来看一个简单的工厂bean的使用案例,来了解其用法,再通过源码说明其加载过程:

  先注册一个Bean标签,

<bean id="stuFactory" class = "fev.test.StudentFactory"/>,之后:
public class StudentFactory implements FactoryBean<Student>{

   @Override
   public Student getObject() throws Exception {
      return new Student("AAA");
   }

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

然后获取:

@Test
public void testStuFactory() throws Exception {
   DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
   new XmlBeanDefinitionReader(factory).loadBeanDefinitions(RETURNS_NULL_CONTEXT);
   Student stuFactory = (Student) factory.getBean("stuFactory");
   System.out.println(stuFactory.toString());
}

再看输出:

在这里有没有发现--我们获取的是一个Student对象,而不是一个StudentFactory对象,现在我们可以知道其就是一个产生需要对象的工厂。

现在我们通过源码来看其加载过程:

         首先我们来看FactoryBeanRegistrySupport的方法:

              

我们抓住其几个关键方法:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            object = doGetObjectFromFactoryBean(factory, beanName);
            // Only post-process and store if not put there already during getObject() call above
            // (e.g. because of circular reference processing triggered by custom getBean calls)
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
               }
               this.factoryBeanObjectCache.put(beanName, object);
            }
         }
         return object;
      }
   }
   else {
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}

两个关键方法,通过

getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)方法,调用
doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)方法产生一个对象一个对象:
object = factory.getObject();也就是调用FactoryBean对象的getObject()返回一个对象,之后将这个对象像三层缓存那样放到
factoryBeanObjectCache中。而postProcessObjectFromFactoryBean方法就是调用BeanPostProcessor接口其操作产生的Bean对象。

然后我们直接看在哪里会调用getObjectFromFactoryBean方法。

   这里可以直接看到,是在AbstractBeanFactory的:

public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

也就是获取bean时:

    直接进入doGetBean方法:这里会有几个地方调用到getObjectForBeanInstance方法,其调用的时机都是一样的:即就是在获取Bean对象之后,

if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         // Explicitly remove instance from singleton cache: It might have been put there
         // eagerly by the creation process, to allow for circular reference resolution.
         // Also remove any beans that received a temporary reference to the bean.
         destroySingleton(beanName);
         throw ex;
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

    在这里我们可以清楚,这个sharedInstance 就是BeanFactory(StudentFactory)对象,而我们要的最终的bean(Student)对象,就是通过getObjectForBeanInstance方法产生的,而getObjectForBeanInstance方法会判断其是不是一个FactoryBean的实例:

protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // Don't let calling code try to dereference the factory if the bean isn't a factory.
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
      }
   }

   // Now we have the bean instance, which may be a normal bean or a FactoryBean.
   // If it's a FactoryBean, we use it to create a bean instance, unless the
   // caller actually wants a reference to the factory.
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
   }

   Object object = null;
   if (mbd == null) {
      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());
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}

  如果是其就调用FactoryBeanRegistrySupport对象的

getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)

方法去创建一个对象,也就是我们上面描叙的。如果不是就直接放行。

 

所以通过上方我们可以清楚FactoryBean、以及FactoryBeanRegistrySupport的逻辑关系:

  正常我们需要一个A,就是通过直接产生一个A,而如果我们想自己去创建这个A对象,我们可以通过这个FactoryBean,也就是B。然后过程是,spring先创建B,然后调用B的方法去创建A。即Spring容器->A,Spring容器-B->A。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值