該系列文章是本人在學習 Spring 的過程當中總結下來的,裏面涉及到相關源碼,可能對讀者不太友好,請結合個人源碼註釋 Spring 源碼分析 GitHub 地址 進行閱讀html
Spring 版本:5.1.14.RELEASEjava
開始閱讀這一系列文章以前,建議先查看《深刻了解 Spring IoC(面試題)》這一篇文章git
該系列其餘文章請查看:《死磕 Spring 之 IoC 篇 - 文章導讀》github
前面的一些列文章對面向資源(XML、Properties)、面向註解定義的 Bean 是如何被解析成 BeanDefinition(Bean 的「前身」),並保存至 BeanDefinitionRegistry 註冊中內心面,實際也是經過 ConcurrentHashMap 進行保存。面試
Spring 底層 IoC 容器 DefaultListableBeanFactory,實現了 BeanFactory 和 BeanDefinitionRegistry 接口,這個時候它處於「就緒狀態」,當咱們顯示或者隱式地調用 getBean(...)
方法時,會觸發加載 Bean 階段,獲取對應的 Bean。在該方法中,若是是單例模式會先從緩存中獲取,已有則直接返回,沒有則根據 BeanDefinition 開始初始化這個 Bean。spring
先來看看 BeanFactory 接口的繼承關係緩存
簡單描述這些接口:安全
org.springframework.beans.factory.BeanFactory
,Spring IoC 容器最基礎的接口,提供依賴查找單個 Bean 的功能session
org.springframework.beans.factory.ListableBeanFactory
,繼承 BeanFactory 接口,提供依賴查找多個 Bean 的功能app
org.springframework.beans.factory.HierarchicalBeanFactory
,繼承 BeanFactory 接口,提供獲取父 BeanFactory 的功能,具備層次性
org.springframework.beans.factory.config.ConfigurableBeanFactory
,繼承 HierarchicalBeanFactory 接口,提供可操做內部相關組件的功能,具備可配置性
org.springframework.beans.factory.config.AutowireCapableBeanFactory
,繼承 BeanFactory 接口,提供可注入的功能,支持依賴注入
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
,繼承上面全部接口,綜合全部特性,還提供可提早初始化全部單例 Bean 的功能
經過這些接口的名稱能夠大體瞭解其用意,接下來咱們來看看它們的實現類的繼承關係
簡單描述這些實現類:
org.springframework.beans.factory.support.AbstractBeanFactory
抽象類,實現 ConfigurableBeanFactory 接口,基礎實現類,Bean 的建立過程交由子類實現org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
抽象類,繼承 AbstractBeanFactory,實現 AutowireCapableBeanFactory 接口,完成 Bean 的建立org.springframework.beans.factory.support.DefaultListableBeanFactory
,Spring 底層 IoC 容器,依賴注入的底層實現其餘的接口和類和 BeanDefinition 註冊中心,別名註冊中心,單例 Bean 註冊中心相關;右下角的 ApplicationContext 與 Spring 應用上下文有關,它的整個體系這裏不作展述,在後面的文章進行分析
org.springframework.beans.factory.support.AbstractBeanFactory
抽象類,實現 ConfigurableBeanFactory 接口,BeanFactory 的基礎實現類,提供依賴查找方法,可獲取 Bean 對象,接下來咱們來看看依賴查找的實現
getBean(String name)
方法,根據名稱獲取 Bean,固然還有許多重載方法,以下:
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); } public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { return doGetBean(name, requiredType, args, false); }
最終都會調用 doGetBean(...)
這個方法
當咱們顯示或者隱式地調用這個方法時,會觸發 Bean 的加載;你是否會有疑問,咱們使用 Spring 的過程當中並不會調用這個方法去獲取 Bean,那這個方法會被誰調用呢?在 ConfigurableListableBeanFactory 接口中提供提早初始化全部單例 Bean 的功能,在 Spring 應用上下文(ApplicationContext)刷新階段會提早初始化全部的單例 Bean,這個提早初始化也是調用 getBean 這個方法,這部份內容在後續分析 Spring 應用上下文的生命週期會講到
doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
方法,獲取一個 Bean,方法以下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // <1> 獲取 `beanName` // 由於入參 `name` 多是別名,也多是 FactoryBean 類型 Bean 的名稱(`&` 開頭,須要去除) // 因此須要獲取真實的 beanName final String beanName = transformedBeanName(name); Object bean; // <2> 先從緩存(僅緩存單例 Bean )中獲取 Bean 對象,這裏緩存指的是 `3` 個 Map // 緩存中也多是正在初始化的 Bean,能夠避免**循環依賴注入**引發的問題 // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); // <3> 若從緩存中獲取到對應的 Bean,且 `args` 參數爲空 if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } // <3.1> 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } // 緩存中沒有對應的 Bean,則開啓 Bean 的加載 else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // <4> 若是**非單例模式**下的 Bean 正在建立,這裏又開始建立,代表存在循環依賴,則直接拋出異常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); // <5> 若是從當前容器中沒有找到對應的 BeanDefinition,則從父容器中加載(若是存在父容器) if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. // <5.1> 獲取 `beanName`,由於多是別名,則進行處理 // 和第 `1` 步不一樣,不須要對 `&` 進行處理,由於進入父容器從新依賴查找 String nameToLookup = originalBeanName(name); // <5.2> 若爲 AbstractBeanFactory 類型,委託父容器的 doGetBean 方法進行處理 // 不然,就是非 Spring IoC 容器,根據參數調用相應的 `getBean(...)`方法 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // <6> 若是不是僅僅作類型檢查,則表示須要建立 Bean,將 `beanName` 標記爲已建立過 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // <7> 從容器中獲取 `beanName` 對應的的 RootBeanDefinition(合併後) final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查是否爲抽象類 checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. // <8> 獲取當前正在建立的 Bean 所依賴對象集合(`depends-on` 配置的依賴) String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // <8.1> 檢測是否存在循環依賴,存在則拋出異常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // <8.2> 將 `beanName` 與 `dep` 之間依賴的關係進行緩存 registerDependentBean(dep, beanName); try { // <8.3> 先建立好依賴的 Bean(從新調用 `getBean(...)` 方法) getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // <9> 開始建立 Bean,不一樣模式建立方式不一樣 if (mbd.isSingleton()) { // <9.1> 單例模式 /* * <9.1.1> 建立 Bean,成功建立則進行緩存,並移除緩存的早期對象 * 建立過程實際調用的下面這個 `createBean(...)` 方法 */ sharedInstance = getSingleton(beanName, // ObjectFactory 實現類 () -> { try { // **【核心】** 建立 Bean 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. // 若是建立過程出現異常,則顯式地從緩存中刪除當前 Bean 相關信息 // 在單例模式下爲了解決循環依賴,建立過程會緩存早期對象,這裏須要進行刪除 destroySingleton(beanName); throw ex; } }); // <9.1.2> 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // <9.2> 原型模式 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { // <9.2.1> 將 `beanName` 標記爲原型模式正在建立 beforePrototypeCreation(beanName); // <9.2.2> **【核心】** 建立 Bean prototypeInstance = createBean(beanName, mbd, args); } finally { // <9.2.3> 將 `beanName` 標記爲不在建立中,照應第 `9.2.1` 步 afterPrototypeCreation(beanName); } // <9.2.4> 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // <9.3> 其餘模式 else { // <9.3.1> 獲取該模式的 Scope 對象 `scope`,不存在則拋出異常 String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { // <9.3.1> 從 `scope` 中獲取 `beanName` 對應的對象(看你的具體實現),不存在則執行**原型模式**的四個步驟進行建立 Object scopedInstance = scope.get(beanName, () -> { // 將 `beanName` 標記爲原型模式正在建立 beforePrototypeCreation(beanName); try { // **【核心】** 建立 Bean return createBean(beanName, mbd, args); } finally { // 將 `beanName` 標記爲不在建立中,照應上一步 afterPrototypeCreation(beanName); } }); // 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. // <10> 若是入參 `requiredType` 不爲空,而且 Bean 不是該類型,則須要進行類型轉換 if (requiredType != null && !requiredType.isInstance(bean)) { try { // <10.1> 經過類型轉換機制,將 Bean 轉換成 `requiredType` 類型 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); // <10.2> 轉換後的 Bean 爲空則拋出異常 if (convertedBean == null) { // 轉換失敗,拋出 BeanNotOfRequiredTypeException 異常 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } // <10.3> 返回類型轉換後的 Bean 對象 return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } // <11> 返回獲取到的 Bean return (T) bean; }
這個方法的處理過程有點長,以下:
獲取 beanName
,由於入參 name
多是別名,也多是 FactoryBean 類型 Bean 的名稱(&
開頭,須要去除),因此須要獲取真實的 beanName
先從緩存(僅緩存單例 Bean )中獲取 Bean 對象,這裏緩存指的是 3
個 Map;緩存中也多是正在初始化的 Bean,能夠避免循環依賴注入引發的問題
若從緩存中獲取到對應的 Bean,且 args
參數爲空
【同】調用 getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
方法
獲取 Bean 的目標對象,scopedInstance
非 FactoryBean 類型直接返回,不然,調用 FactoryBean#getObject() 獲取目標對象
緩存中沒有對應的 Bean,則開啓 Bean 的加載
若是非單例模式下的 Bean 正在建立,這裏又開始建立,代表存在循環依賴,則直接拋出異常
若是從當前容器中沒有找到對應的 BeanDefinition,則從父容器中加載(若是存在父容器)
beanName
,由於多是別名,則進行處理,和第 1
步不一樣,不須要對 &
進行處理,由於進入父容器從新依賴查找getBean(...)
方法若是不是僅僅作類型檢查,則表示須要建立 Bean,將 beanName
標記爲已建立過,在後面的循環依賴檢查中會使用到
從容器中獲取 beanName
對應的的 RootBeanDefinition(合併後),調用 getMergedLocalBeanDefinition(String beanName)
方法
獲取當前正在建立的 Bean 所依賴對象集合(depends-on
配置的依賴)
beanName
與 dep
之間依賴的關係進行緩存getBean(...)
方法)開始建立 Bean,不一樣模式建立方式不一樣
單例模式
建立 Bean,成功建立則進行緩存,並移除緩存的早期對象,調用 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法
【核心】入參的 ObjectFactory 實現類就是調用的 AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
方法
【同】 和上面的 3.1
相同操做
原型模式
beanName
標記爲非單例模式正在建立AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
方法beanName
標記爲不在建立中,照應第 9.2.1
步3.1
相同操做其餘模式
scope
,不存在則拋出異常scope
中獲取 beanName
對應的對象(看你的具體實現),不存在則執行原型模式的四個步驟進行建立若是入參 requiredType
不爲空,而且 Bean 不是該類型,則須要進行類型轉換
requiredType
類型返回獲取到的 Bean
歸納:
能夠看到這個方法加載 Bean 的過程當中,會先從緩存中獲取單例模式的 Bean;
不論是從緩存中獲取的仍是新建立的,都會進行處理,若是是 FactoryBean 類型則調用其 getObject() 獲取目標對象;
BeanFactory 可能有父容器,若是當前容器找不到 BeanDefinition 則會嘗試讓父容器建立;
建立 Bean 的任務交由 AbstractAutowireCapableBeanFactory 去完成;
若是獲取到的 Bean 不是咱們想要類型,會經過類型轉換機制轉換成目標類型
接下來依次分析上述過程的相關步驟(doGetBean(...)
)
對應代碼段:
// AbstractBeanFactory.java final String beanName = transformedBeanName(name);
由於入參 name
多是別名,也多是 FactoryBean 類型 Bean 的名稱(&
開頭,須要去除),因此須要進行一番轉換,以下:
// AbstractBeanFactory.java protected String transformedBeanName(String name) { return canonicalName(BeanFactoryUtils.transformedBeanName(name)); } // BeanFactoryUtils.java public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { return name; } // 獲取 name 對應的 beanName, // 不爲 null 則返回 `transformedBeanNameCache` 緩存中對應的 beanName, // 爲 null 則對 name 進行處理,將前綴 '&' 去除,直至沒有 '&',而後放入 `transformedBeanNameCache` 緩存中,並返回處理後的 beanName return transformedBeanNameCache.computeIfAbsent(name, beanName -> { do { beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); } while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); return beanName; }); } // SimpleAliasRegistry.java public String canonicalName(String name) { String canonicalName = name; // Handle aliasing... String resolvedName; // 循環,從 aliasMap 中,獲取到最終的 beanName do { resolvedName = this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while (resolvedName != null); return canonicalName; }
過程並不複雜,先將前綴 &
去除(若是存在),若是是別名則獲取對應的 beanName
定義了一個 FactoryBean 類型的 Bean,名稱爲
user
,經過user
獲取 Bean,獲取到的是 FactoryBean#getObject() 返回的對象(只會被調用一次)經過
&user
獲取 Bean,獲取到的是 FactoryBean 自己這個對象
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 Object sharedInstance = getSingleton(beanName);
單例模式的 Bean 被建立後會緩存,爲了不循環依賴注入,在建立過程會臨時緩存正在建立的 Bean(早期 Bean),在後續文章會講到,從緩存中獲取對象過程以下:
// DefaultSingletonBeanRegistry.java public Object getSingleton(String beanName) { return getSingleton(beanName, true); } protected Object getSingleton(String beanName, boolean allowEarlyReference) { // <1> **【一級 Map】**從單例緩存 `singletonObjects` 中獲取 beanName 對應的 Bean Object singletonObject = this.singletonObjects.get(beanName); // <2> 若是**一級 Map**中不存在,且當前 beanName 正在建立 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // <2.1> 對 `singletonObjects` 加鎖 synchronized (this.singletonObjects) { // <2.2> **【二級 Map】**從 `earlySingletonObjects` 集合中獲取,裏面會保存從 **三級 Map** 獲取到的正在初始化的 Bean singletonObject = this.earlySingletonObjects.get(beanName); // <2.3> 若是**二級 Map** 中不存在,且容許提早建立 if (singletonObject == null && allowEarlyReference) { // <2.3.1> **【三級 Map】**從 `singletonFactories` 中獲取對應的 ObjectFactory 實現類 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 若是從**三級 Map** 中存在對應的對象,則進行下面的處理 if (singletonFactory != null) { // <2.3.2> 調用 ObjectFactory#getOject() 方法,獲取目標 Bean 對象(早期半成品) singletonObject = singletonFactory.getObject(); // <2.3.3> 將目標對象放入**二級 Map** this.earlySingletonObjects.put(beanName, singletonObject); // <2.3.4> 從**三級 Map**移除 `beanName` this.singletonFactories.remove(beanName); } } } } // <3> 返回從緩存中獲取的對象 return singletonObject; }
過程以下:
singletonObjects
中獲取 beanName 對應的 BeansingletonObjects
加鎖earlySingletonObjects
集合中獲取,裏面會保存從 三級 Map 獲取到的正在初始化的 BeansingletonFactories
中獲取對應的 ObjectFactory 實現類,若是從三級 Map 中存在對應的對象,則進行下面的處理這個過程對應《深刻了解 Spring IoC(面試題)》中的BeanFactory 是如何處理循環依賴問題
通常狀況下,Spring 經過反射機制利用 Bean 的 beanClass 屬性指定實現類來實例化 Bean。某些狀況下,Bean 的實例化過程比較複雜,若是按照傳統的方式,則須要提供大量的配置信息,配置方式的靈活性有限,這時採用編碼的方式可能會獲得一個簡單的方案。Spring 爲此提供了一個 FactoryBean 的工廠 Bean 接口,用戶能夠經過實現該接口定製實例化 Bean 的邏輯。
FactoryBean 接口對於 Spring 框架自己也很是重要,其內部就提供了大量 FactoryBean 的實現。它們隱藏了實例化過程當中一些複雜細節,給上層應用帶來了便利。
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
不論是從緩存中獲取的仍是新建立的,都會調用這個方法進行處理,若是是 FactoryBean 類型則調用其 getObject() 獲取目標對象
// AbstractBeanFactory.java 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` 以 `&` 開頭,說明想要獲取 FactoryBean,則校驗其**正確性** if (BeanFactoryUtils.isFactoryDereference(name)) { // <1.1> 若是是 NullBean 空對象,則直接返回 if (beanInstance instanceof NullBean) { return beanInstance; } // <1.2> 若是不是 FactoryBean 類型,則拋出異常 if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, 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() 方法獲取目標對象 // <2> 若是 `beanInstance` 不是 FactoryBean 類型,不須要再處理則直接返回 // 或者(表示是 FactoryBean 類型) `name` 以 `&` 開頭,表示你想要獲取實際 FactoryBean 對象,則直接返回 // 還不符合條件的話,表示是 FactoryBean,須要獲取 getObject() 返回目標對象 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; // <3> 若是入參沒有傳 BeanDefinition,則從 `factoryBeanObjectCache` 緩存中獲取對應的 Bean 對象 // 入參傳了 BeanDefinition 表示這個 Bean 是剛建立的,不走緩存,須要調用其 getObject() 方法獲取目標對象 // `factoryBeanObjectCache`:FactoryBean#getObject() 調用一次後返回的目標對象緩存在這裏 if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } // <4> 若第 `3` 步獲取的對象爲空,則須要調用 FactoryBean#getObject() 得到對象 if (object == null) { // Return bean instance from factory. // <4.1> 將 `beanInstance` 轉換成 FactoryBean 類型 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. // <4.2> 若是入參沒有傳 BeanDefinition 而且當前容器存在對應的 BeanDefinition if (mbd == null && containsBeanDefinition(beanName)) { // 獲取對應的 RootBeanDefinition(合併後) mbd = getMergedLocalBeanDefinition(beanName); } // 是不是用戶定義的(不是 Spring 建立解析出來的) boolean synthetic = (mbd != null && mbd.isSynthetic()); // <4.3> **【核心】**經過 FactoryBean 得到目標對象,單例模式會緩存在 `factoryBeanObjectCache` 中 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
過程以下:
若 name
以 &
開頭,說明想要獲取 FactoryBean,則校驗其正確性
若是 beanInstance
不是 FactoryBean 類型,不須要再處理則直接返回;或者(表示是 FactoryBean 類型) name
以 &
開頭,表示你想要獲取實際 FactoryBean 對象,則直接返回;還不符合條件的話,表示是 FactoryBean,須要獲取 getObject() 返回目標對象,往下處理
若是入參沒有傳 BeanDefinition,則從 factoryBeanObjectCache
緩存中獲取對應的 Bean 對象,以下:
// FactoryBeanRegistrySupport.java protected Object getCachedObjectForFactoryBean(String beanName) { return this.factoryBeanObjectCache.get(beanName); }
factoryBeanObjectCache
:FactoryBean#getObject() 調用一次後返回的目標對象緩存在這裏
入參傳了 BeanDefinition 表示這個 Bean 是剛建立的,不走緩存,須要調用其 getObject() 方法獲取目標對象
若第 3
步獲取的對象爲空,則須要調用 FactoryBean#getObject() 得到對象
beanInstance
轉換成 FactoryBean 類型factoryBeanObjectCache
中,調用 getObjectFromFactoryBean(FactoryBean<?>, String, boolean)
方法getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)
方法,獲取 FactoryBean 的目標對象,方法以下:
// FactoryBeanRegistrySupport.java protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // <1> `factory` 爲單例模式,且單例 Bean 緩存中存在 `beanName` 對應的 FactoryBean 對象 if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { // <1.1> 獲取單例鎖,保證安全 // <1.2> 從 `factoryBeanObjectCache` 緩存中獲取 FactoryBean#getObject() 建立的目標對象 Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // <1.3> 則根據 `factory` 獲取目標對象,調用 FactoryBean#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) // <1.4> 這裏再進行一次校驗,看是否在緩存中存在 FactoryBean 建立的目標對象,若是有則優先從緩存中獲取 // 保證 FactoryBean#getObject() 只能被調用一次 // 沒有的話,則對剛獲取到的目標對象進行接下來的處理 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // <1.5> 是否須要後續處理,這個 FactoryBean 的前身 BeanDefinition 是否由 Spring 解析出來的,一般狀況下都是 if (shouldPostProcess) { // <1.5.1> 若該 FactoryBean 處於建立中,則直接返回這個目標對象,不進行接下來的處理過程 if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } // <1.5.2> 前置處理,將 `beanName` 標誌爲正在建立 beforeSingletonCreation(beanName); try { // <1.5.3> 對經過 FactoryBean 獲取的目標對象進行後置處理 // 遍歷全部的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的處理) object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } finally { // <1.5.4> 後置處理,將 `beanName` 標誌爲不在建立中 afterSingletonCreation(beanName); } } // <1.6> 若是緩存中存在 `beanName` 對應的 FactoryBean 對象 // 上面不是判斷了嗎?也可能在上面的處理過程會有所變化,因此這裏在作一層判斷 // 目的:緩存 FactoryBean 建立的目標對象,則須要保證 FactoryBean 自己這個對象存在緩存中 if (containsSingleton(beanName)) { // <1.6.1> 將這個 FactoryBean 建立的目標對象保存至 `factoryBeanObjectCache` this.factoryBeanObjectCache.put(beanName, object); } } } // <1.7> 返回 FactoryBean 建立的目標對象 return object; } } // <2> `factory` 非單例模式,或單例 Bean 緩存中不存在 `beanName` 對應的 FactoryBean 對象 else { // <2.1> 則根據 `factory` 獲取目標對象,調用 FactoryBean#getObject() 方法 Object object = doGetObjectFromFactoryBean(factory, beanName); // <2.2> 是否須要後續處理,這個 FactoryBean 的前身 BeanDefinition 是否由 Spring 解析出來的,一般狀況下都是 if (shouldPostProcess) { try { // <2.2.1> 對經過 FactoryBean 獲取的目標對象進行後置處理 // 遍歷全部的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的處理) object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } // <2.3> 返回 FactoryBean 建立的目標對象,非單例模式不會進行緩存 return object; } }
過程以下:
factory
爲單例模式,且單例 Bean 緩存中存在 beanName
對應的 FactoryBean 對象
獲取單例鎖,保證安全
從 factoryBeanObjectCache
緩存中獲取 FactoryBean#getObject() 建立的目標對象
則根據 factory
獲取目標對象,調用 FactoryBean#getObject() 方法(反射機制)
這裏再進行一次校驗(第 1.2
已經判斷過),看是否在緩存中存在 FactoryBean 建立的目標對象,若是有則優先從緩存中獲取,保證 FactoryBean#getObject() 只能被調用一次;沒有的話,則對剛獲取到的目標對象進行接下來的處理
是否須要後續處理,這個 FactoryBean 的 BeanDefinition 是否由 Spring 解析出來的,一般狀況下都是
若該 FactoryBean 處於建立中,則直接返回這個目標對象,不進行接下來的處理過程
前置處理,將 beanName
標誌爲正在建立
對經過 FactoryBean 獲取的目標對象進行後置處理,遍歷全部的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的處理)
後置處理,將 beanName
標誌爲不在建立中
若是緩存中存在 beanName
對應的 FactoryBean 對象,上面不是判斷了嗎(第 1
步判斷過)?
也可能在上面的處理過程會有所變化,因此這裏在作一層判斷,目的:緩存 FactoryBean 建立的目標對象,則須要保證 FactoryBean 自己這個對象存在緩存中
factoryBeanObjectCache
返回 FactoryBean 建立的目標對象
factory
非單例模式,或單例 Bean 緩存中不存在 beanName
對應的 FactoryBean 對象
factory
獲取目標對象,調用 FactoryBean#getObject() 方法(反射機制)歸納:調用 FactoryBean#getObject() 獲取目標對象,單例模式會緩存起來;過程當中 Sping 考慮到各類狀況,例如保證單例模式下 FactoryBean#getObject() 只調用一次,是否須要進行後置處理。
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } protected boolean isPrototypeCurrentlyInCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); return (curVal != null && (curVal.equals(beanName) // 相等 || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含 }
prototypesCurrentlyInCreation
中保存非單例模式下正在建立的 Bean 的名稱,這裏又從新建立,表示出現循環依賴,則直接拋出異常
Spring 對於非單例模式的 Bean 沒法進行相關緩存,也就沒法處理循環依賴的狀況,選擇了直接拋出異常
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 BeanFactory parentBeanFactory = getParentBeanFactory(); // <5> 若是從當前容器中沒有找到對應的 BeanDefinition,則從父容器中加載(若是存在父容器) if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. // <5.1> 獲取 `beanName`,由於多是別名,則進行處理 // 和第 `1` 步不一樣,不須要對 `&` 進行處理,由於進入父容器從新依賴查找 String nameToLookup = originalBeanName(name); // <5.2> 若爲 AbstractBeanFactory 類型,委託父容器的 doGetBean 方法進行處理 // 不然,就是非 Spring IoC 容器,根據參數調用相應的 `getBean(...)`方法 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } }
若是當前 BeanFactory 沒有對應的 BeanDefinition,也就沒法建立 Bean,可是若是存在父 BeanFactory,則將接下來的操做交由父 BeanFactory,找不到會層層找上去,若是全部 BeanFactory 都找不到對應的 BeanDefinition 最終會拋出異常。
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 // <6> 若是不是僅僅作類型檢查,則表示須要建立 Bean,將 `beanName` 標記爲已建立過 if (!typeCheckOnly) { markBeanAsCreated(beanName); }
若是不是僅僅作類型檢查,則調用 markBeanAsCreated(String beanName)
方法,以下:
// AbstractBeanFactory.java protected void markBeanAsCreated(String beanName) { // 沒有建立 if (!this.alreadyCreated.contains(beanName)) { // 加上全局鎖 synchronized (this.mergedBeanDefinitions) { // 再次檢查一次:DCL 雙檢查模式 if (!this.alreadyCreated.contains(beanName)) { // Let the bean definition get re-merged now that we're actually creating // the bean... just in case some of its metadata changed in the meantime. // 從 mergedBeanDefinitions 中刪除 beanName,並在下次訪問時從新建立它 clearMergedBeanDefinition(beanName); // 添加到已建立 bean 集合中 this.alreadyCreated.add(beanName); } } } }
將這個 beanName
保存在 alreadyCreated
集合中(SetFromMap),在後面的循環依賴檢查中會使用到
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 // <7> 從容器中獲取 `beanName` 對應的的 RootBeanDefinition(合併後) final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查是否爲抽象類 checkMergedBeanDefinition(mbd, beanName, args);
由於咱們定義的 Bean 大多數都被 Spring 解析成 GenericBeanDefinition 類型,具備父子關係,則須要獲取最終的 BeanDefinition;若是存在父子關係,則會進行一系列的合併,轉換成 RootBeanDefinition 對象,調用 getMergedLocalBeanDefinition(String beanName)
方法,以下:
// AbstractBeanFactory.java protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. // 從 `mergedBeanDefinitions` 緩存中獲取合併後的 RootBeanDefinition,存在則直接返回 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null) { return mbd; } // 獲取 BeanDefinition 並轉換成,若是存在父子關係則進行合併 return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); } protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) throws BeanDefinitionStoreException { return getMergedBeanDefinition(beanName, bd, null); } protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { // 加鎖 synchronized (this.mergedBeanDefinitions) { RootBeanDefinition mbd = null; // Check with full lock now in order to enforce the same merged instance. if (containingBd == null) { mbd = this.mergedBeanDefinitions.get(beanName); } if (mbd == null) { // 若是沒有父類則直接轉換成 RootBeanDefinition 對象 if (bd.getParentName() == null) { // Use copy of given root bean definition. if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } // 有父類則進行合併 else { // Child bean definition: needs to be merged with parent. BeanDefinition pbd; try { // 獲取父類的對應的 BeanDefinition 對象 String parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without an AbstractBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } // Deep copy with overridden values. mbd = new RootBeanDefinition(pbd); // 父子合併 mbd.overrideFrom(bd); } // Set default singleton scope, if not configured before. if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON); } // A bean contained in a non-singleton bean cannot be a singleton itself. // Let's correct this on the fly here, since this might be the result of // parent-child merging for the outer bean, in which case the original inner bean // definition will not have inherited the merged outer bean's singleton status. if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // Cache the merged bean definition for the time being // (it might still get re-merged later on in order to pick up metadata changes) if (containingBd == null && isCacheBeanMetadata()) { // 放入緩存中 this.mergedBeanDefinitions.put(beanName, mbd); } } return mbd; } }
過程大體以下:
mergedBeanDefinitions
緩存中獲取合併後的 RootBeanDefinition,存在則直接返回,不存在則進行後面的操做後續還會對合並後的 RootBeanDefinition 對象進行檢查,若是是抽象的,則拋出異常
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 // Guarantee initialization of beans that the current bean depends on. // <8> 獲取當前正在建立的 Bean 所依賴對象集合(`depends-on` 配置的依賴) String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // <8.1> 檢測是否存在循環依賴,存在則拋出異常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // <8.2> 將 `beanName` 與 `dep` 之間依賴的關係進行緩存 registerDependentBean(dep, beanName); try { // <8.3> 先建立好依賴的 Bean(從新調用 `getBean(...)` 方法) getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } }
每一個 Bean 不必定是單獨工做的,能夠經過 depends-on
配置依賴的 Bean,其餘 Bean 也能夠依賴它
對於依賴的 Bean,會優先加載,因此在 Spring 的加載順序中,在初始化某個 Bean 的時候,首先會初始化這個 Bean 的依賴
在初始化依賴的 Bean 以前,會調用 isDependent(String beanName, String dependentBeanName)
方法,判斷是否出現循環依賴,方法以下:
DefaultSingletonBeanRegistry.java protected boolean isDependent(String beanName, String dependentBeanName) { synchronized (this.dependentBeanMap) { return isDependent(beanName, dependentBeanName, null); } } private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) { // <1> `alreadySeen` 中已經檢測過該 `beanName` 則直接返回 `false` if (alreadySeen != null && alreadySeen.contains(beanName)) { return false; } // <2> 獲取最終的 `beanName`,由於多是別名,須要進行相關處理 String canonicalName = canonicalName(beanName); // <3> 從 `dependentBeanMap` 中獲取依賴 `beanName` 的 Bean 集合 Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); // <4> 沒有 Bean 依賴該 `beanName`,也就不存在循環依賴,返回 `false` if (dependentBeans == null) { return false; } // <5> 依賴 `beanName` 的 Bean 們包含 `dependentBeanName`,表示出現循環依賴,返回 `true` if (dependentBeans.contains(dependentBeanName)) { // `beanName` 與 `dependentBeanName` 相互依賴 return true; } // <6> 對依賴該 `beanName` 的 Bean 們進行檢查,看它們是否與 `dependentBeanName` 存在依賴,遞歸處理 for (String transitiveDependency : dependentBeans) { if (alreadySeen == null) { alreadySeen = new HashSet<>(); } alreadySeen.add(beanName); if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } return false; }
過程大體以下:
alreadySeen
中已經檢測過該 beanName
則直接返回 false
beanName
,由於多是別名,須要進行相關處理dependentBeanMap
中獲取依賴 beanName
的 Bean 集合beanName
,也就不存在循環依賴,返回 false
beanName
的 Bean 們包含 dependentBeanName
,表示出現循環依賴,返回 true
beanName
的 Bean 們進行檢查,看它們是否與 dependentBeanName
存在依賴,遞歸處理判斷是否出現循環依賴的過程有點繞,須要花點時間理解一下。例如:如今檢查 A ->(依賴)B,看是否出現循環依賴,我獲取到依賴 A 的全部 Bean,看 B 是否依賴這裏面的 Bean,若是出現 A -> B -> C -> A,那就出現循環依賴了。若是出現循環依賴,則會拋出異常,因此咱們說 Spring 處理了單例 Bean 的循環依賴注入比較好一點。
將 beanName
與 dep
(beanName
的依賴)之間依賴的關係進行緩存,調用 registerDependentBean(String beanName, String dependentBeanName)
方法,以下:
DefaultSingletonBeanRegistry.java public void registerDependentBean(String beanName, String dependentBeanName) { String canonicalName = canonicalName(beanName); // 對應關係:beanName -> 依賴 beanName 的集合 synchronized (this.dependentBeanMap) { Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8)); if (!dependentBeans.add(dependentBeanName)) { return; } } // 對應關係:beanName - > beanName 的依賴的集合 synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); dependenciesForBean.add(canonicalName); } }
將二者的依賴關係保存起來,目的是在 isDependent
方法中判斷是否出現循環依賴
加載 beanName
依賴的 Bean,一樣是調用 AbstractBeanFactory#getBean(String dep)
方法,也就是本文開頭講的這個方法
Spring 的做用域劃分爲三種:單例模式、原型模式、其餘模式,會依次進行判斷,而後進行建立,建立過程都是同樣的,主要是存儲範圍不同
request
做用域會將 Bean 存儲在 ServletRequest 上下文中;session
做用域會將 Bean 存儲在 HttpSession 中;application
做用域會將 Bean 存儲在 ServletContext 中對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 if (mbd.isSingleton()) { // <9.1> 單例模式 /* * <9.1.1> 建立 Bean,成功建立則進行緩存,並移除緩存的早期對象 * 建立過程實際調用的下面這個 `createBean(...)` 方法 */ sharedInstance = getSingleton(beanName, // ObjectFactory 實現類 () -> { try { // **【核心】** 建立 Bean 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. // 若是建立過程出現異常,則顯式地從緩存中刪除當前 Bean 相關信息 // 在單例模式下爲了解決循環依賴,建立過程會緩存早期對象,這裏須要進行刪除 destroySingleton(beanName); throw ex; } }); // <9.1.2> 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
若是是單例模式,建立過程大體以下:
調用 DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法
建立 Bean,成功建立則進行緩存,並移除緩存的早期對象,建立過程實際調用的下面這個 AbstractAutowireCapableBeanFactory#createBean(...)
方法
FactoryBean 的處理,在前面 3. FactoryBean 的處理 中已經分析過
DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法,單例模式下獲取單例 Bean,以下:
// DefaultSingletonBeanRegistry.java public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 全局加鎖 synchronized (this.singletonObjects) { // <1> 從 `singletonObjects` 單例 Bean 的緩存中獲取 Bean(再檢查一遍),存在則直接返回,不然開始建立 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // <2> 將 `beanName` 標記爲單例模式正在建立 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { /** * <3> 建立 Bean,實際調用 * {@link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])} 方法 */ singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } // <4> 將 `beanName` 標記爲不在建立中,照應第 `2` 步 afterSingletonCreation(beanName); } // <5> 若是這裏是新建立的單例模式 Bean,則在 `singletonObjects` 中進行緩存(無序),移除緩存的早期對象 // 並在 `registeredSingletons` 中保存 `beanName`,保證註冊順序 if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
過程大體以下:
singletonObjects
單例 Bean 的緩存中獲取 Bean(再檢查一遍),存在則直接返回,不然開始建立beanName
標記爲單例模式正在建立AbstractAutowireCapableBeanFactory#createBean(...)
方法beanName
標記爲不在建立中,照應第 2
步singletonObjects
中進行緩存(無序),移除緩存的早期對象,並在 registeredSingletons
中保存 beanName
,保證註冊順序AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
方法,建立 Bean,整個過程大體以下:
上面涉及到 Bean 生命週期的大部分階段,將會在後續的文章中依次分析
對應代碼段:
// AbstractBeanFactory.java // <9.2> 原型模式 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { // <9.2.1> 將 `beanName` 標記爲**非單例模式**正在建立 beforePrototypeCreation(beanName); // <9.2.2> **【核心】** 建立 Bean prototypeInstance = createBean(beanName, mbd, args); } finally { // <9.2.3> 將 `beanName` 標記爲不在建立中,照應第 `9.2.1` 步 afterPrototypeCreation(beanName); } // <9.2.4> 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
過程大體以下:
beanName
標記爲非單例模式正在建立AbstractAutowireCapableBeanFactory#createBean(...)
方法,這裏沒有緩存,每次加載 Bean 都會建立一個對象beanName
標記爲不在建立中,照應第 1
步對應代碼段:
// AbstractBeanFactory.java // <9.3> 其餘模式 else { // <9.3.1> 獲取該模式的 Scope 對象 `scope`,不存在則拋出異常 String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { // <9.3.2> 從 `scope` 中獲取 `beanName` 對應的對象(看你的具體實現),不存在則執行**原型模式**的四個步驟進行建立 Object scopedInstance = scope.get(beanName, () -> { // 將 `beanName` 標記爲**非單例模式**式正在建立 beforePrototypeCreation(beanName); try { // **【核心】** 建立 Bean return createBean(beanName, mbd, args); } finally { // 將 `beanName` 標記爲不在建立中,照應上一步 afterPrototypeCreation(beanName); } }); // 獲取 Bean 的目標對象,`scopedInstance` 非 FactoryBean 類型直接返回 // 不然,調用 FactoryBean#getObject() 獲取目標對象 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } }
過程以下:
scope
,不存在則拋出異常scope
中獲取 beanName
對應的對象(看你的具體實現),不存在則執行原型模式的四個步驟進行建立想要自定義一個做用域,能夠實現 org.springframework.beans.factory.config.Scope
接口,並往 Spring 應用上下文註冊便可
對應代碼段:
// AbstractBeanFactory#doGetBean(...) 方法 // <10> 若是入參 `requiredType` 不爲空,而且 Bean 不是該類型,則須要進行類型轉換 if (requiredType != null && !requiredType.isInstance(bean)) { try { // <10.1> 經過類型轉換機制,將 Bean 轉換成 `requiredType` 類型 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); // <10.2> 轉換後的 Bean 爲空則拋出異常 if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } // <10.3> 返回類型轉換後的 Bean 對象 return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } }
若是入參 requiredType
不爲空,而且 Bean 不是該類型,則須要進行類型轉換,過程以下:
requiredType
類型,對 Spring 的類型轉換機制感興趣的小夥伴能夠本身研究,參考 org.springframework.core.convert.support.DefaultConversionService
本文對 BeanFactory 接口的體系結構進行了分析,得知 DefaultListableBeanFactory 是 BeanFactory 的最底層實現,也就是 Spring 的底層 IoC 容器。接着分析了 AbstractBeanFactory
的 getBean(...)
方法,當咱們顯示或者隱式地調用這個方法時,會觸發 Bean 的加載。上面全部小節對 Bean 的加載過程進行了分析,我已經有序地在每一個小節面前添加了序號,這些序號對應着加載過程當中的順序。
不一樣做用域的 Bean 的建立,底層都會調用 AbstractAutowireCapableBeanFactory
的 createBean(...)
方法進行建立,建立 Bean 的過程涉及到 Bean 生命週期的大部分階段,例如實例化階段、屬性賦值階段、Aware 接口回調階段、初始化階段都是在這個方法中完成的,整個建立過程將在後續的文章進行分析。