Spring 源码解析之FactoryBean
看一个例子
FactoryBeanDemo类
@Service public class FactoryBeanDemo implements FactoryBean { @Override public Object getObject() throws Exception { return new FactoryB(); } @Override public Class<?> getObjectType() { return FactoryB.class; } }
FactoryB类`
public class FactoryB { }
测试代码
public void test4() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(cn.com.dq); FactoryB factoryB = (FactoryB) applicationContext.getBean(factoryBeanDemo); System.out.println(factoryB); FactoryBeanDemo factoryBeanDemo = (FactoryBeanDemo) applicationContext.getBean(&factoryBeanDemo); System.out.println(factoryBeanDemo); }
输出结果
从上面的代码可以启发2点思考
1.我们通过beanName=[factoryBeanDemo]拿到的bean不是FactoryBeanDemo的实例,而是FactoryB 的实例
2.我们要想拿到FactoryBeanDemo的实例而是通过&factoryBeanDemo拿到
下面我们从源码上分析上述情况
源码分析
在bean的实例化中,当bean实例化完成以后都会看到这样一行代码,如下:
AbstractBeanFactory类
doGetBean()方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { ... 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; } }); //该方法是FactoryBean接口的调用入口 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } ... }`
FactoryBean接口的调用入口getObjectForBeanInstance();
getObjectForBeanInstance()
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. //如果实例不是FactoryBean类型的,或者name是以&号开头的,则直接返回实例 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } //如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的 Object object = null; if (mbd == null) { //从缓存里面拿FactoryBean类型的实例 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; }
如下代码
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; }
BeanFactoryUtils的isFactoryDereference方法如下
public static boolean isFactoryDereference(@Nullable String name) { return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); }
1.上述代码可以解释要拿到FactoryBeanDemo的实例则是通过&factoryBeanDemo拿到
2.如果beanName不是以&开头,并且beanInstance是FactoryBean类型,会优先在factoryBeanObjectCache缓存中拿。
3.第一次肯定是拿不到的,则会执行getObjectFromFactoryBean()方法
FactoryBeanRegistrySupport类
getObjectFromFactoryBean()方法
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) { //调用getObject方法 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) { if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } beforeSingletonCreation(beanName); try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, Post-processing of FactoryBean's singleton object failed, ex); } finally { afterSingletonCreation(beanName); } } if (containsSingleton(beanName)) { //把实例缓存到factoryBeanObjectCache map中,这个是单独缓存FactoryBean类型实例的map 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; } }
该方法执行2个比较重要的操作
1.doGetObjectFromFactoryBean()
2.将执行doGetObjectFromFactoryBean()方法返回的bean的实例放入factoryBeanObjectCache缓存中
doGetObjectFromFactoryBean()方法
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = getAccessControlContext(); try { object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //调用getObject方法 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; }
上述代码可以看到最终调用到了FactoryBean的getObject()方法
回到示例代码FactoryBean的getObject()的方法返回的是FactoryB的实例
通过上述的源码分析就能解释我们通过beanName=[factoryBeanDemo]拿到的bean不是FactoryBeanDemo的实例,而是FactoryB 的实例
总结
1.FactoryBean接口的调用入口是在bean的实例化完成以后
2.bean在实现FactoryBean接口后通过beanName拿到的不是bean本身的实例而是FactoryBean接口中getObject()方法返回的实例
3.bean在实现FactoryBean接口后要拿到bean本身的实例,则是通过&+beanName拿到