摘要:本文結合《Spring源碼深度解析》來分析Spring 5.0.6版本的源代碼。若有描述錯誤之處,歡迎指正。
在getBean方法中,getObjectForBeanlnstance是個髙頻率使用的方法,無論是從緩存中獲得bean還是根據不同的scope策略加載bean。總之,我們得到bean的實例后要做的第一步就是調用這個方法來檢測一下正確性,其實就是用於檢測當前bean是否是FactoryBean類型的bean,如果是,那么需要調用該bean對應的FactoryBean實例中的getObject()作為返回值。
無論是從緩存中獲取到的bean還是通過不同的scope策略加載的bean都只是最原始的bean狀態,並不一定是我們最終想要的bean。舉個例子,假如我們需要對工廠bean進行處理,那么這里得到的其實是工廠bean的初始狀態,但是我們真正需要的是工廠bean中定義的 factory-method方法中返回的bean,而getObjectForBeanlnstance方法就是完成這個工作的。
/** * Get the object for the given bean instance, either the bean * instance itself or its created object in case of a FactoryBean. * @param beanInstance the shared bean instance * @param name name that may include factory dereference prefix * @param beanName the canonical bean name * @param mbd the merged bean definition * @return the object to expose for the bean */ 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. // 如果指定的name是工廠相關(以&為前綴)且 beanInstance又不是FactoryBean類型則驗證不通過 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. // 現在我們有了個bean的實例,這個實例可能會是正常的bean或者是FactoryBean // 如果是FactoryBean我們使用它創建實例,似是如果用戶想要直接獲取工廠實例而不是工廠的getObject方法對應的實例,那么傳人的name應該加入前綴& if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 加栽 FactoryBean Object object = null; if (mbd == null) { // 嘗試從緩存中加栽bean object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. //到這里已經明確知道beanInstance—定是FactoryBean類型 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. // containsBeanDefinition檢測beanDefinitionMap中也就是在所有已經加載的類中檢測是否定義beanName if (mbd == null && containsBeanDefinition(beanName)) { // 將存儲 XML 配置文件的 GenericBeanDefinition 轉換為 RootBeanDefinition, 如果指定beanName是子Bean的話同時會合並父類的相關屬性 mbd = getMergedLocalBeanDefinition(beanName); } // 是否是用戶定義的而不是應用程序本身定義的 boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
從上面的代碼來看,其實這個方法並沒有什么重要的信息,大多是些輔助代碼以及一些功能性的判斷,而真正的核心代碼卻委托給了getObjectFromFactoryBean,我們來看看 getObjectForBeanlnstance 所做的工作。
(1)對FactoryBean正確性的驗證。
(2)對非FactoryBean不做任何處理。
(3)對bean進行轉換。
(4)將從 Factory 中解析 bean 的工作委托給 getObjectFromFactoryBean。
/** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @param shouldPostProcess whether the bean is subject to post-processing * @return the object obtained from the FactoryBean * @throws BeanCreationException if FactoryBean object creation failed * @see org.springframework.beans.factory.FactoryBean#getObject() */ 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 { // 調用ObjectFactory的后處理器 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)) { 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; } }
很遺憾,在這個代碼中我們還是沒有看到想要看到的代碼,在這個方法里只做了一件事情, 就是返回的bean如果是單例的,那就必須要保證全局唯一,同時,也因為是單例的,所以不必重復創建,可以使用緩存來提高性能,也就是說已經加載過就要記錄下來以便於下次復用, 否則的話就直接獲取了。
在doGetObjectFromFactoryBean方法中我們終於看到了我們想要看到的方法,也就足object = factory.getObjcct(),是的,就是這句代碼,我們的歷程猶如剝洋蔥一樣,一層一層的直到最內部的代碼實現,雖然很簡單。
/** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @return the object obtained from the FactoryBean * @throws BeanCreationException if FactoryBean object creation failed * @see org.springframework.beans.factory.FactoryBean#getObject() */ 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的調用方法,如果bean聲明為FactoryBean類型,則當提取bean時提取的並不是FactoryBean,而是FactoryBean中對應的getObject方法返冋的bean,而doGetObjectFromFactoryBean正是實現這個功能的。但是,我們看到在上面的方法中除了調用object = factory.getObject()得到我們想要的結果后並沒有直接返回,而是接下來又做了些后處理的操作,這個又是做什么用的呢?於是我們跟蹤進入AbstractAutowireCapableBeanFactory 類的 postProcessObjectFromFactoryBean 方法:
@Override protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { return applyBeanPostProcessorsAfterInitialization(object, beanName); } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
對於后處理器的使用我們還未過多接觸,后續章節會使用大量篇幅介紹,這里,我們只需了解在Spring獲取bean的規則中有這樣一條:盡可能保證所有bean初始化后都會調用注冊的BeanPostProcessor的postProcessAfterlnitialization方法進行處理,在實際開發過程中大可以針對此特性設計自己的業務邏輯。