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拿到
下面我們從原始碼上分析上述情況
原始碼分析
首先例項化的是實現了FactoryBean介面的類
在beanName前面拼接了一個&
if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } }
在bean的例項化中,當bean例項化完成以後都會看到這樣一行程式碼,如下:
AbstractBeanFactory類
doGetBean()方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
...
final String beanName = transformedBeanName(name);
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);
}
...
}`
此時有個beanName,name;beanName是沒有&符號的,name是有&符號的
factoryBean這個類本身例項化完成以後放在一級快取中,factoryBean例項化完成以後
接著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.上述程式碼說明FactoryBean例項化完成以後就返回了,如果執行getBean操作,beanName加了&此時在一級快取拿到FactoryBean真正的例項,然後返回,所以可以解釋要拿到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拿到
4.FactoryBean優先例項化,例項化完成以後存在一級快取singletonObjects中,接著會呼叫FactoryBean的getObject方法,將使用者自己new的例項存在factoryBeanObjectCache快取中
5.在getBean的時候,加了&,就是在spring一級快取拿到例項後,直接返回了,如果沒加&,就會在factoryBeanObjectCache快取中拿,拿到以後返回,沒有就呼叫FactoryBean的介面方法getObject返回,然後更新factoryBeanObjectCache快取