spring原始碼(10)從快取中獲取到單例bean的後續操作(對FactoryBean的處理)
阿新 • • 發佈:2019-02-03
從快取中獲取到例項,doGetBean第一步就是對我們輸入的name做了處理。
- 去除FactoryBean的修飾符,也就是name=”&a”,最終處理為name=”a”
- 取指定別名最終所指向的beanName
在從快取中獲取例項時,getSingleton(beanName),引數是已經處理的。我們知道如果想要獲取FactoryBean getObject方法對應的例項,那麼name需要加字首&。所以通過getSingletom獲取到的可能是FactoryBean例項。
getObjectForBeanInstance就是對以上的糾正。
總體流程圖如下:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//如果name的以&為開頭,但是beanInstance又不是FactoryBean型別,則丟擲BeanIsNotAFactoryException
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
//如果beanInstance不是FactoryBean型別,或者不是以&開頭,則直接返回例項
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//以下步驟處理以&開頭的name,即FactoryBean
Object object = null;
if (mbd == null) {
//嘗試從快取中載入bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//到這裡已經明確知道beanInstance為FactoryBean型別
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//將儲存XML配置檔案的GernericBeanDefinition轉換成RootBeanDefinition
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果factoryBean為單例子,並且已經在快取中存在
if (factory.isSingleton() && containsSingleton(beanName)) {
//同步訪問singletonObjects
synchronized (getSingletonMutex()) {
//從快取中獲取bean例項,如果存在直接返回
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 (object != null && 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 != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {//如果不是單例
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
//後續處理
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
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(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//直接呼叫factorybean的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 && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}