前言
在《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方法 》