前言

在《spring中FactoryBean是什麼bean》一文中,帶著小夥伴學習了spring中的FactoryBean,瞭解了到了FactoryBean其實是一種生產Bean的bean,也就是FactroyBean的前世是Bean,今生還是Bean,小夥伴要疑惑了都是Bean,但是此Bean非彼Bean。今天帶著小夥伴從原始碼的角度來分析下FactoryBean,重點是getObjectForBeanInstance方法的分析。

前世

在前面說到FactoryBean的前世是一個Bean,是指是一個FactoryBean的例項。先來看下getObjectForBeanInstance方法,

/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a 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.
//1、判斷name是否以&開頭
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.
//beanInstance不是FactoryBean的例項或name以&開頭
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
} Object object = null;
//mbd即beanDefinition為空,從快取中取
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
//快取中沒有,則呼叫FactoryBean的getObject方法,返回其物件
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;
}

看該方法上的註釋,

Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.

用我蹩腳的英語翻譯過來大概是這個意思,

返回給定的bean Instance的一個物件,該物件可能是bean instance或者是由bean instance(是一個FactoryBean)建立的一個物件。

意思很明白了,該方法有可能返回的是一個FactoryBean的例項,也可能是由FactroyBean生產的例項,關鍵看方法引數中的前兩個,

Object beanInstance  spring容器中的一個bean

String name   可能含有&字首的名稱

String beanName  bean的規範名稱

RootBeanDefintion mbd  BeanDefinition

看下面的表格更容易理解該方法在各種情況下的返回值,

beanInstance name 返回值
FactoryBean的例項 帶有& beanInstance
不是FactoryBean的例項 帶有& beanInstance
FactoryBean的例項 不帶& beanInstance生產的物件
不是FactoryBean的例項 不帶& beanInstance

通過上面得表格再結合程式碼就很容易理解,只要是返回beanInstance物件,那麼就是FactroyBean的前世,下面看FactoryBean的今生。

今生

這裡有兩個方法需要分析,分別是getCachedObjectForFactoryBean和getObjectFromFactoryBean。第一個方法是從快取中獲取,也就是說使用FactoryBean生產的bean會單獨放在快取中,非singletonObjects中,這點務必要注意。

getCachedObjectForFactoryBean

先看下該方法的定義,

@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}

可以看到很簡單就是通過名稱從factoryBeanObjectCache中取物件。factoryBeanObjectCache肯定是個map了

/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

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) {
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);
}
}
//把生產的例項物件放到factoryBeanObjectCache快取中
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//呼叫getObject方法
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;
}
}

該方法就比較複雜了,主要有doGetObjectFromFactoryBean、beforeSingletonCreation、postProcessObjectFromFactoryBean、afterSingletonCreation方法,重要的一個是doGetFromFactroyBean,也就是真正幹活生產bean的方法。其定義如下,其餘方法可自行檢視

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 {
//呼叫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) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}

在上文中的註釋部分已經看到最終呼叫了getObject方法,也就是返回的是FactoryBean中getObject方法的返回值。

總結

主要分析了FactoryBean的底層原始碼,判斷是返回FactoryBean的例項還是返回其生產的例項,主要看bean的型別是否為FactoryBean和名稱中是否帶&。

推薦:《spring中FactoryBean是什麼bean

一次性講清楚spring中bean的生命週期之一:getSingleton方法 》