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拿到