盤點 SpringIOC : Bean 建立主流程

總文檔 :文章目錄
Github : github.com/black-anthtml

一 . 前言

Spring IOC 體系是一個很值得深刻和研究的結構 , 只有本身真正的讀一遍 , 纔能有更好的理解.java

這篇文章主要說明一下 CreateBean 整個環節中的大流程轉換 , 便於查找問題的緣由 :git

此篇文章的目的 :github

  • 梳理Bean 的建立流程 , 便於後續查找問題點
  • 梳理過程當中的參數狀況 , 減小Debug的需求
  • 梳理總體家族體系

Bean 建立的幾個觸發場景 :緩存

  • BeanFactory 的 #getBean(...) 方法來請求某個實例對象的時候
  • 使用 ApplicationContext 容器時 , 會在啓動時當即註冊部分 Bean

二 . 流程梳理

先來看一個很常見的圖 , 來源於 @ topjava.cn/article/139…markdown

beanSelf.jpg

一樣的 , 這篇的流程整理也是按照此流程 , 先看一下整個流程大綱app

> 實例化過程
    1 實例化Bean 對象 : Spring 容器根據實例化策略對 Bean 進行實例化
        ?- 經常使用策略模式 , 一般包括反射和 CGLIB 動態字節碼
            - SimpleInstantiationStrategy : 反射
            - CglibSubclassingInstantiationStrategy : 經過 CGLIB 的動態字節碼 (默認)
    	- createBeanInstance(...) 方法實現 ,返回 BeanWrapper 
            - BeanWrapper  : 低級 Bean 基礎結構的核心接口
            ?- 低級 Bean : 無任何屬性
    	- BeanWrapperImpl 對  Bean 進行「包裹」 ,用於注入Bean 屬性
    	|- InstantiationStrategy -> SimpleInstantiationStrategy 
    	|- SimpleInstantiationStrategy -> CglibSubclassingInstantiationStrategy 
    2 注入對象屬性
        |- 實例化完成後,若是該 bean 設置了一些屬性的話,則利用 set 方法設置一些屬性
    3 檢測 , 激活 Aware
    	| -感知 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    	|- 若是該 Bean 實現了 BeanNameAware 接口
            |- 則調用 #setBeanName(String beanName) 方法
    4 BeanPostProcessor 前置處理
        |- 若是該 bean 實現了 BeanClassLoaderAware 接口
            |- 則調用 setBeanClassLoader(ClassLoader classLoader) 方法。
        |- 若是該 bean 實現了 BeanFactoryAware接口
            |- 則調用 setBeanFactory(BeanFactory beanFactory) 方法
        |- 若是該容器註冊了 BeanPostProcessor
            |- 則會調用#postProcessBeforeInitialization
            |- 完成 bean 前置處理
    5 檢查 InitializingBean 和 init-method
        |- 若是該 bean 實現了 InitializingBean 接口
            |-則調用#afterPropertiesSet() 方法
        |- 若是該 bean 配置了 init-method 方法,則調用其指定的方法。
    6 BeanPostProcessor 後置處理
        |- 初始化完成後,若是該容器註冊了 BeanPostProcessor 
            |- 則會調用 #postProcessAfterInitialization,完成 bean 的後置處理。
    7 註冊必要的Destruction 回調
    8 使用Bean
        |- 對象完成初始化,開始方法調用
    9 檢查 DisposableBean 和 destory-method
    	|- 在容器進行關閉以前,若是該 bean 實現了 DisposableBean 接口
            |- 則調用 #destroy() 方法
            |- 在容器進行關閉以前,若是該 bean 配置了 destroy-method 
            |- 則調用其指定的方法。

複製代碼

2.1 實例化建立

引言 : 誰調用的 ?
ide

doGetBean 會有2種調用途徑 :函數

一種是 ApplicationContext 加載的時候 , 會初始化當前容器須要的 Bean :
C- SpringApplication # run
C- SpringApplication # prepareContext
C- SpringApplication # applyInitializers : 調用 ApplicationContextInitializer 集合 , 分別執行對應的 initialize
C- ApplicationContextInitializer # initialize
C- ConditionEvaluationReport # get
C- AbstractBeanFactory # getBeanoop

第二種是容器必要 Bean 加載完成後 ,refresh 時處理全部的 Bean

  • C- SpringApplication # run
  • C- SpringApplication # refreshContext
  • C- AbstractApplicationContext # refresh()
    • 此處refresh 中有多處會調用 getBean
    • C- AbstractApplicationContext # invokeBeanFactoryPostProcessors
    • C- AbstractApplicationContext # registerBeanPostProcessors
    • C- AbstractApplicationContext # onRefresh();
    • C- AbstractApplicationContext # finishBeanFactoryInitialization
  • C- AbstractBeanFactory # getBean

PS : 另外還有一種就是由於依賴關係被遞歸調用的

2.1.1 doGetBean 入口

C171- AbstractBeanFactory 
	M171_01- getBean(String name, Class<T> requiredType)
            ?- 直接調用 doGetBean , 這裏會根據類型不一樣調用不一樣的 getBean

複製代碼

doGetBean 能夠分爲 5 個階段

  • 階段一 : 生成 beanName 後嘗試從單例緩存中獲取
  • 階段二 : 單例緩存中獲取失敗後 ,嘗試 ParentBeanFactory 中獲取
  • 階段三 : 依賴檢查 , 保證初始化當前bean所依賴的bean
  • 階段四 : 三種不一樣的類型得到 Bean 實例 (Singleton / prototype / other)
  • 階段五 : 此時 Bean 已經準備完成了 , 此處檢查所需的類型是否與實際bean實例的類型匹配 , 不符須要轉換
// 核心方法一 : 
M171_02- doGetBean( String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)
        	
    // 階段一 : 生成 beanName 後嘗試從單例緩存中獲取
    1- transformedBeanName 生成 beanName -> PS:M171_02_01
    2- getSingleton(beanName) : 單例方式獲取一個 Bean , 循環依賴就是這個環節處理 -> -> PS:M171_02_02 
    IF- sharedInstance != null : 若是此時已經生成 , 且 args 爲空不須要繼續加載
        - getObjectForBeanInstance(sharedInstance, name, beanName, null) 
        
    // 階段二 : 單例緩存中獲取失敗後 ,嘗試 ParentBeanFactory 中獲取
    ELSE- 
        3- isPrototypeCurrentlyInCreation(beanName) : 若是是原型模式且存在循環依賴則拋出異常
        4- getParentBeanFactory() : 檢查這個工廠中是否存在bean定義
            ?- 若是工廠中已經存在了 , 會有四種狀況會直接 return -> PS:M171_02_03
            4.1- AbstractBeanFactory :  parentBeanFactory.doGetBean
            4.2- args != null : parentBeanFactory.getBean(nameToLookup, args)
            4.3- requiredType != null: parentBeanFactory.getBean(nameToLookup, requiredType)
            4.4- 都不符合 : parentBeanFactory.getBean(nameToLookup)
        - 若是爲類型檢查而獲取實例,而不是實際使用 , 則將指定的bean標記爲已經建立 -> PS:M171_02_04
        - RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName) + checkMergedBeanDefinition
            ?- RootBeanDefinition的獲取和檢查  LV171_001
            
        // 階段三 : 依賴檢查 , 保證初始化當前bean所依賴的bean
        -  對於屬性 LV171_001:mbd , 經過 getDependsOn 獲取全部依賴
        FOR- 循環全部的依賴 , 分別調用 registerDependentBean + getBean 進行遞歸操做
        
        // 階段四 : 三種不一樣的類型得到 Bean 實例
        5- 判斷 Bean 的類型不一樣建立 Bean -> PS:M171_02_05 
            5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
            5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
            5.3- 其餘 : 主要是經過 Scope 控制域 + Prototype 流程
            
        // 階段五 : 此時 Bean 已經準備完成了 , 此處檢查所需的類型是否與實際bean實例的類型匹配
        IF- 若是實例不匹配 , 則須要轉換, 轉換後直接返回
            - return getTypeConverter().convertIfNecessary(bean, requiredType)
        // 若是上面沒有返回 , 則直接發返回本來的Bean 
                        
                       
// 其餘方法
M171_10- getSingleton(String beanName, ObjectFactory<?> singletonFactory) : 獲取單例 Bean
M171_20- getObject() : 這裏實際是調用 FactoryBean
    ?- 這裏會經過一個 方法回調的語法糖 , 調用 createBean , 整個就連起來了 -> M173_02
                        
                        
// 核心方法二 : 實例化 Bean 
// 首先要知道 , 前面傳過來的是什麼 : TODO 
M171_ - getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)

                        
// PS : doGetBean 在附錄中展現
複製代碼

2.1.2 doGetBean 補充節點

PS:M171_02_01 獲取 beanName

--> canonicalName(BeanFactoryUtils.transformedBeanName(name))
----> 
C181- SimpleAliasRegistry
    F181_01- Map<String, String> aliasMap
    M- canonicalName(BeanFactoryUtils.transformedBeanName(name))
        - 主要是從 F181_01 中獲取 alias 別名
            ?- PS : 這裏的代碼有點意思 , 看樣子是爲了解決別名鏈的問題 , 即別名對應的還有別名 , 直到取不出來

public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    do {
        
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    // 循環獲取別名對應的是否存在別名 , 直到獲取不到
    }while (resolvedName != null);
    return canonicalName;
}

複製代碼

PS:M171_02_03 爲何四種狀況會直接返回 ?

4.1- AbstractBeanFactory :  parentBeanFactory.doGetBean
4.2- args != null : parentBeanFactory.getBean(nameToLookup, args)
    ?- 使用顯式參數委託給父類
4.3- requiredType != null: parentBeanFactory.getBean(nameToLookup, requiredType)
    ?- 委託給標準的getBean方法
4.4- 都不符合 : parentBeanFactory.getBean(nameToLookup)
    ?- Pro2
    
// 這裏直接返回是由於存在父 BeanFactory , 且存在 BeanDefinition , 這就意味着ParentBeanFactory 能處理 , 基於 Pro 1 的緣由 , 選擇直接返回 
    
    
// Pro 1 : 爲何從父工廠裏面獲取 -> BeanFactory parentBeanFactory = getParentBeanFactory();
這是一個遞歸操做 , 也是仿照雙親委派的方式來處理 , 即先有父對象來加載對應的對象

一樣的 , 當進入 doGet 的時候 , 默認經過父方法去加載 , 若是父方法處理完成了 , 即加載出 Bean 了 , 就直接返回
好處呢 , 想了一下 , 能夠保證每一個實現能專一於其自己須要處理的 Bean , 而不須要關注本來就會加載的 Bean 
回顧一下雙親委派的目的 : 避免重複加載 + 避免核心類篡改    
    
// Pro 2 : 四種方式去返回的區別
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


    
複製代碼

PS:M171_02_04 對於只檢查的那樣處理有什麼目的 ?

這裏若是是隻檢查而無需建立 , 會在 markBeanAsCreated 方法中作2件事
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);    

這樣的目的是爲了即標註方法已經檢查成功 , 而避免走不必的反覆流程 ,容許bean工廠爲重複建立指定bean而優化其緩存 
--> 實際邏輯    

// Step 1 : alreadyCreated 是什麼 ?
Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
    ?- alreadyCreated 包含 至少已經建立過一次的bean的名稱的 Set 集合

// Step 2 : 如何利用這個對象 ?
1 : AbstractAutowireCapableBeanFactory # getTypeForFactoryBean
    ?- 這裏會經過這個對象校驗引用的工廠bean還不存在,那麼在這裏退出——不會僅僅爲了獲取FactoryBean的對象類型而強制建立另外一個bean
    
2 : clearMetadata 時 , 須要判斷是否爲空

 

複製代碼

PS:M171_02_05 三種不一樣方式的本質區別 ?

相同點 :  最終調用 getObjectForBeanInstance    
5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
    - 首先經過 getSingleton 方法, 保證加載的惟一性
    - 回調 createBean 建立 Bean
    - 經過 getObjectForBeanInstance 實例化真正的 Bean
    
5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
    - 仔細看就能發現 , 沒有相關的 scope 對象控制 , 直接進行建立
    
5.3- 其餘 : 主要是經過 Scope 控制域 + Prototype 流程
    - 它是 singleton 的結合體 , 
    - 首先會準備一個 Scope 對象用於控制 Scope 域內的 Bean 狀況
    - 再調用和 Prototype 一致的流程進行建立
        

複製代碼

PS:M171_02_06 sharedInstance 和 bean 的區別

這裏能夠看到 , 首先經過 createBean 建立了一個 Object 對象 sharedInstance , 又經過 getObjectForBeanInstance 生成了一個 Bean ,他們有什麼本質的區別 ?

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

// 這就涉及到 Bean 的工廠了 , 通常狀況下 , createBean 建立的 Bean 就是一個 完整的 Bean
// 可是 ,若是它是一個FactoryBean,須要使用它來建立一個bean實例,除非調用者實際上想要一個對工廠的引用。

複製代碼

sharedInstance 中的 Bean 是已經走完 Bean 建立流程的 Bean了 image.png

2.1.3 AbstractBeanFactory # createBean

C171- AbstractBeanFactory 
	M171_03- createBean(String beanName, RootBeanDefinition mbd, Object[] args) 
            P- mbd :  BeanDefinition 對象 , 已經合併了父類屬性
            p- args : 用於構造函數或者工廠方法建立 Bean 實例對象的參數

複製代碼

2.1.4 AbstractAutowireCapableBeanFactory # createBean 主流程

C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
    M173_02- createBean(String beanName, RootBeanDefinition mbd,Object[] args)
        ?- M170_01 方法的默認實現
        LV173_02_01- RootBeanDefinition mbdToUse : 內部屬性 , 用於標識根 BeanDefinition 
        1- Class<?> resolvedClass = resolveBeanClass(mbd, beanName) -> PS:M173_02_01
            ?- 解析得到指定 BeanDefinition 的 class 屬性 -> M173_04 IF- 解析的 Class 不爲 null , 且存在 BeanClassBeanClassName - new RootBeanDefinition(mbd) - mbdToUse.setBeanClass(resolvedClass) 2- mbdToUse.prepareMethodOverrides() : 處理 Overrides 屬性 -> PS:M173_02_02 - GetMethodOverrides().getOverrides() - prepareMethodOverride(MethodOverride mo) 3- Object bean = resolveBeforeInstantiation(beanName, mbdToUse) --- 實例化的前置處理 
        - 若是 bean 不爲 null , 則直接返回 (直接返回是由於上一步生成了一個代理類 ,AOP )
        4- Object beanInstance = doCreateBean(beanName, mbdToUse, args); --- 建立對象
    M173_03- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    M173_04- resolveBeanClass : 將bean類名解析爲class引用 // PS:M173_02_01 RootBeanDefinition // 確保bean類在此時被實際解析,若是動態解析的class不能存儲在共享合併bean定義中,則克隆bean定義 RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
}

// PS:M173_02_02 prepareMethodOverrides 處理 Overrides
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    if (hasMethodOverrides()) {
        getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
    }
}

// >>>>>>> 對應 prepareMethodOverride 方法
C- AbstractBeanDefinition
    M-  prepareMethodOverride(MethodOverride mo)
        1- ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName())
            ?- 獲取當前Method Name 對應的方法數量
        2- 若是沒有對應方法 ,拋出 BeanDefinitionValidationException 
        3- 若是 count = 1 , 將 Overloaded 標記爲未重載 , 在後續調用的時候,能夠直接找到方法而不須要進行方法參數的校驗


// M173_02 源碼簡介
M- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    -  beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
    -  beanInstance = this.doCreateBean(beanName, mbdToUse, args); -> M173_05
    

複製代碼

doCreateBean 主流程

doCreate 分爲幾大步驟 :

C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory   
    M173_05- doCreateBean(beanName, mbdToUse, args) : 建立 Bean 對象
        ?- 非代理對象的 常規Bean 建立 , 主要節點有如下幾個
        - 準備 BeanWrapper : BeanWrapper 是對 Bean 的包裝
        - 若是單例模型,則從未完成的 FactoryBean 緩存中刪除
        - createBeanInstance(beanName, mbd, args) : 進入Bean 建立流程 , 建立一個 Bean 的封裝 BeanWrapper 
            ?- 這裏的獲取若是是單例 , 則直接獲取 , 而且移除緩存中的對象 
            ?- 不然調用 createBeanInstance 獲取
        - instanceWrapper.getWrappedInstance();
            ?- 包裝的實例對象
        - instanceWrapper.getWrappedClass();
            ?- 包裝的實例對象的類型
    	IF- applyMergedBeanDefinitionPostProcessors
            ?- 若是有後置處理 , 則在此處進行後置處理 , synchronized 上鎖
    	IF- addSingletonFactory 
            ?- 若是是單例 , 且容許+ 存在循環依賴 , 則在此處進行單例模式的處理
    	- populateBean : 屬性注入操做 -> M173_30
    	- initializeBean : 初始化 Bean 
            ?- 此處會進行 Init-Method 的處理 ->  PS:M173_05_03
    	IF- getSingleton 
            ?- 循環依賴狀況 , 則會遞歸初始依賴 bean , 此處返回的是一個用於循環處理的空對象
            ?- 2種狀況 , 返回早期對象或者 getDependentBeans 遞歸全部的 -> PS:M173_05_01
    	- registerDisposableBeanIfNecessary
    M173_07- prepareMethodOverrides
        - 獲取全部的 Overrides , 而且依次調用 prepareMethodOverride -> M173_08
        
    M173_08- prepareMethodOverride
        - getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride)
            ?- Foreach 全部的 Overrides , 調用 prepareMethodOverride
    M173_10- autowireByName : 根據屬性名稱,完成自動依賴注入
    M173_11- autowireByType : 根據屬性類型,完成自動依賴注入
        - resolveDependency -> resolveDependency
    M173_12- resolveDependency : 完成了全部注入屬性的獲取
        - doResolveDependency
    M173_13- doResolveDependency	
    M173_15- applyPropertyValues : 應用到已經實例化的 bean 中
    M173_50- initializeBean



// doCreateBean 核心代碼流程 
M- doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) : createBean 主流程
    - mbd.isSingleton() : 判斷後獲取 BeanWrapper (ConfigurationClassPostProcessor) 
        - instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        - instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    - this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    - this.populateBean(beanName, mbd, instanceWrapper) : 主要是屬性填充
        - Step 1 : bw == null&&mbd.hasPropertyValues() : BeanWrapper 空值判斷
        - Step 2 : this.getBeanPostProcessors().iterator() : 迭代BeanPostProcessors
            - ibp.postProcessAfterInstantiation : 此處是 After 
        - Step 3 : 獲取 PropertyValue , 而且經過 autowireByName 或者 autowireByType 注入
        - Step 4 : hasInstantiationAwareBeanPostProcessors
            - this.getBeanPostProcessors().iterator();
            - ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
        - Step 5 : 
        - Step 6 : this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs) : 依賴檢查
        - Step 7 : this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs) : 
    - this.initializeBean(beanName, exposedObject, mbd);
    - this.registerDisposableBeanIfNecessary(beanName, bean, mbd);     
    
    
// 附錄 : M173_05 doCreateBean 源碼比較長 ,放在結尾
複製代碼

PS:M173_05_01 : 遞歸循環細說

在 doCreateBean 中 , 會對循環依賴進行處理

// 循環依賴狀況 , 則會遞歸初始依賴 bean , 此處返回的是一個用於循環處理的空對象
// 2種狀況 , 返回早期對象或者 getDependentBeans 遞歸全部的
if (earlySingletonExposure) {
    // 參考循環依賴那一章 , 這裏可能會返回一個未完善的前置對象引用
    // 只有存在循環依賴 , 這裏纔不會爲空
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        // 判斷存在循環依賴 
        }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            // 返回依賴於指定bean的全部bean的名稱(若是有的話)
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
                // 若是有被用於類型檢查以外的其餘目的時 ,則不能夠刪除 -> PS:M173_05_03
                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                    // 無需刪除 , 則添加
                    actualDependentBeans.add(dependentBean);
                }
            }
            // 由於上文添加 , 這裏就造成依賴
            if (!actualDependentBeans.isEmpty()) {
                throw new BeanCurrentlyInCreationException(".....");
            }
        }
    }
}

// PS:M173_05_03 : 什麼是其餘的目的 ? 
removeSingletonIfCreatedForTypeCheckOnly 核心是校驗 alreadyCreated 
1 . 若是 alreadyCreated 已經存在了 ,則說明對應的對象已經建立完成了 
2 . 若是對應的對象已經建立完了了 , 其中依賴的當前對象不是正在建立的對象
3 . 可是其中的屬性又不是當前的對象 , 說明循環依賴不成立 , 依賴已經串了

@ https://www.cnblogs.com/qinzj/p/11485018.html

複製代碼

M173_05 doCreateBean 源碼

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {

        // Step 1 : 準備 BeanWrapper : BeanWrapper 是對 Bean 的包裝
        BeanWrapper instanceWrapper = null;
        
        if (mbd.isSingleton()) {
            // 若是單例模型,則從未完成的 FactoryBean 緩存中刪除
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 進入Bean 建立流程 , 建立一個 Bean 的封裝 BeanWrapper 
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 獲取包裝的實例對象
        final Object bean = instanceWrapper.getWrappedInstance();
        // 包裝的實例對象的類型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Step 2 : 若是有後置處理 , 則在此處進行後置處理 , synchronized 上鎖
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException("....");
                }
                mbd.postProcessed = true;
            }
        }

        // Step 3 :若是是單例 , 且容許+ 存在循環依賴 , 則在此處進行單例模式的處理
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {

            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Step 4 : 此處會進行 Init-Method 的處理 -> PS:M173_05_03
        Object exposedObject = bean;
        try {
            // Step 5 :屬性注入操做 -> M173_30
            populateBean(beanName, mbd, instanceWrapper);
            // Step 6 : 初始化 Bean 
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException("....");
            }
        }
    
    
        // 循環依賴狀況 , 則會遞歸初始依賴 bean , 此處返回的是一個用於循環處理的空對象
        // 2種狀況 , 返回早期對象或者 getDependentBeans 遞歸全部的 -> PS:M173_05_01
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(".....");
                    }
                }
            }
        }

        // Step 7 : 註冊 Bean
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException("...");
        }

        return exposedObject;
    }

複製代碼

總結

其中有幾個錨點 :

Step 1 : 入口

入口中主要是會統籌管理 , 若是緩存中有 , 則直接使用 , 若是沒有 , 則區別 Scope 分別使用不一樣的方式獲取一個 Bean

- C171- AbstractBeanFactory 
    - M171_02- doGetBean  

複製代碼

Step 2 : 建立主流程

建立主流程就是建立一個完整的 Bean , 走一個 Bean 建立的完整週期 , 包括 process , 屬性注入 , init 初始化等等 , 這些咱們在後面的文章中再詳細說說

// Step 1 : 
C173- AbstractAutowireCapableBeanFactory 
    M173_02- createBea
    
// Step 2 : 
C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory   
    M173_05- doCreateBean

複製代碼

附錄

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        // 階段一 : 生成 beanName 後嘗試從單例緩存中獲取
        final String beanName = transformedBeanName(name);
        Object bean;
        
        // 單例方式獲取一個 Bean , 循環依賴就是這個環節處理 -> -> PS:M171_02_02 
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            // 直接從實例化中獲取 Bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 階段二 : 單例緩存中獲取失敗後 
            if (isPrototypeCurrentlyInCreation(beanName)) {
                // 若是是原型模式且存在循環依賴則拋出異常
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 檢查這個工廠中是否存在bean定義
            BeanFactory parentBeanFactory = getParentBeanFactory();
            
            // 若是工廠中已經存在了 , 會有四種狀況會直接 return -> PS:M171_02_03
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            // 若是爲類型檢查而獲取實例,而不是實際使用 , 則將指定的bean標記爲已經建立 -> PS:M171_02_04
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // RootBeanDefinition的獲取和檢查 LV171_001
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 階段三 : 依賴檢查 , 保證初始化當前bean所依賴的bean
                // 對於屬性 LV171_001:mbd , 經過 getDependsOn 獲取全部依賴
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 循環全部的依賴 , 分別調用 registerDependentBean + getBean 進行遞歸操做
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(.....);
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(.....);
                        }
                    }
                }

                // 階段四 : 三種不一樣的類型得到 Bean 實例
                // 判斷 Bean 的類型不一樣建立 Bean -> PS:M171_02_05 
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    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 {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(....);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 階段五 : 此時 Bean 已經準備完成了 , 此處檢查所需的類型是否與實際bean實例的類型匹配
        // 若是實例不匹配 , 則須要轉換, 轉換後直接返回
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        // 若是上面沒有返回 , 則直接發返回本來的Bean 
        return (T) bean;
    }

複製代碼

參考與感謝

寫這個以前 , 還跑過去再讀了一遍 , 很感謝死磕系列開啓了 IOC 的源碼學習

-> @ topjava.cn/article/139…

相關文章
相關標籤/搜索