国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Spring IOC:CreateBean環(huán)節中的流程轉換

發(fā)布時(shí)間:2021-07-05 18:40 來(lái)源:腳本之家 閱讀:0 作者:AntBlack 欄目: 開(kāi)發(fā)技術(shù)

目錄

          一 . 前言

          此篇文章的目的 :

          • 梳理Bean 的創(chuàng )建流程 , 便于后續查找問(wèn)題點(diǎn)
          • 梳理過(guò)程中的參數情況 , 減少Debug的需求
          • 梳理整體家族體系

          Bean 創(chuàng )建的幾個(gè)觸發(fā)場(chǎng)景 :

          • BeanFactory 的 #getBean(...) 方法來(lái)請求某個(gè)實(shí)例對象的時(shí)候
          • 使用 ApplicationContext 容器時(shí) , 會(huì )在啟動(dòng)時(shí)立即注冊部分 Bean

          二 . 流程梳理

          先來(lái)看一個(gè)很常見(jiàn)的圖 , 來(lái)源于

          同樣的 , 這篇的流程整理也是按照此流程 , 先看一下整個(gè)流程大綱

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

          2.1 實(shí)例化創(chuàng )建

          引言 : 誰(shuí)調用的 ?

          doGetBean 會(huì )有2種調用途徑 :

          一種是 ApplicationContext 加載的時(shí)候 , 會(huì )初始化當前容器需要的 Bean :

          • C- SpringApplication # run
          • C- SpringApplication # prepareContext
          • C- SpringApplication # applyInitializers : 調用 ApplicationContextInitializer 集合 , 分別執行對應的 initialize
          • C- ApplicationContextInitializer # initialize
          • C- ConditionEvaluationReport # get
          • C- AbstractBeanFactory # getBean

          第二種是容器必要 Bean 加載完成后 ,refresh 時(shí)處理所有的 Bean

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

          PS : 另外還有一種就是因為依賴(lài)關(guān)系被遞歸調用的

          2.1.1 doGetBean 入口

          C171- AbstractBeanFactory 
          	M171_01- getBean(String name, Class<T> requiredType)
                      ?- 直接調用 doGetBean , 這里會(huì )根據類(lèi)型不同調用不同的 getBean
          
          

          doGetBean 可以分為 5 個(gè)階段

          • 階段一 : 生成 beanName 后嘗試從單例緩存中獲取
          • 階段二 : 單例緩存中獲取失敗后 ,嘗試 ParentBeanFactory 中獲取
          • 階段三 : 依賴(lài)檢查 , 保證初始化當前bean所依賴(lài)的bean
          • 階段四 : 三種不同的類(lèi)型獲得 Bean 實(shí)例 (Singleton / prototype / other)
          • 階段五 : 此時(shí) Bean 已經(jīng)準備完成了 , 此處檢查所需的類(lèi)型是否與實(shí)際bean實(shí)例的類(lèi)型匹配 , 不符需要轉換
          // 核心方法一 : 
          M171_02- doGetBean( String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)
                  	
              // 階段一 : 生成 beanName 后嘗試從單例緩存中獲取
              1- transformedBeanName 生成 beanName -> PS:M171_02_01
              2- getSingleton(beanName) : 單例方式獲取一個(gè) Bean , 循環(huán)依賴(lài)就是這個(gè)環(huán)節處理 -> -> PS:M171_02_02 
              IF- sharedInstance != null : 如果此時(shí)已經(jīng)生成 , 且 args 為空不需要繼續加載
                  - getObjectForBeanInstance(sharedInstance, name, beanName, null) 
                  
              // 階段二 : 單例緩存中獲取失敗后 ,嘗試 ParentBeanFactory 中獲取
              ELSE- 
                  3- isPrototypeCurrentlyInCreation(beanName) : 如果是原型模式且存在循環(huán)依賴(lài)則拋出異常
                  4- getParentBeanFactory() : 檢查這個(gè)工廠(chǎng)中是否存在bean定義
                      ?- 如果工廠(chǎng)中已經(jīng)存在了 , 會(huì )有四種情況會(huì )直接 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)
                  - 如果為類(lèi)型檢查而獲取實(shí)例,而不是實(shí)際使用 , 則將指定的bean標記為已經(jīng)創(chuàng  )建 -> PS:M171_02_04
                  - RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName) + checkMergedBeanDefinition
                      ?- RootBeanDefinition的獲取和檢查  LV171_001
                      
                  // 階段三 : 依賴(lài)檢查 , 保證初始化當前bean所依賴(lài)的bean
                  -  對于屬性 LV171_001:mbd , 通過(guò) getDependsOn 獲取所有依賴(lài)
                  FOR- 循環(huán)所有的依賴(lài) , 分別調用 registerDependentBean + getBean 進(jìn)行遞歸操作
                  
                  // 階段四 : 三種不同的類(lèi)型獲得 Bean 實(shí)例
                  5- 判斷 Bean 的類(lèi)型不同創(chuàng  )建 Bean -> PS:M171_02_05 
                      5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
                      5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
                      5.3- 其他 : 主要是通過(guò) Scope 控制域 + Prototype 流程
                      
                  // 階段五 : 此時(shí) Bean 已經(jīng)準備完成了 , 此處檢查所需的類(lèi)型是否與實(shí)際bean實(shí)例的類(lèi)型匹配
                  IF- 如果實(shí)例不匹配 , 則需要轉換, 轉換后直接返回
                      - return getTypeConverter().convertIfNecessary(bean, requiredType)
                  // 如果上面沒(méi)有返回 , 則直接發(fā)返回原本的Bean 
                                  
                                 
          // 其他方法
          M171_10- getSingleton(String beanName, ObjectFactory<?> singletonFactory) : 獲取單例 Bean
          M171_20- getObject() : 這里實(shí)際是調用 FactoryBean
              ?- 這里會(huì )通過(guò)一個(gè) 方法回調的語(yǔ)法糖 , 調用 createBean , 整個(gè)就連起來(lái)了 -> M173_02
                                  
                                  
          // 核心方法二 : 實(shí)例化 Bean    
          // 首先要知道 , 前面傳過(guò)來(lái)的是什么 : TODO                     
          M171_ - getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
          
                                  
          // PS : doGetBean 在附錄中展示
          

          2.1.2 doGetBean 補充節點(diǎn)

          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 : 這里的代碼有點(diǎn)意思 , 看樣子是為了解決別名鏈的問(wèn)題 , 即別名對應的還有別名 , 直到取不出來(lái)
          
          public String canonicalName(String name) {
              String canonicalName = name;
              String resolvedName;
              do {
                  
                  resolvedName = this.aliasMap.get(canonicalName);
                  if (resolvedName != null) {
                      canonicalName = resolvedName;
                  }
              // 循環(huán)獲取別名對應的是否存在別名 , 直到獲取不到
              }while (resolvedName != null);
              return canonicalName;
          }
          
          

          PS:M171_02_03 為什么四種情況會(huì )直接返回 ?

          4.1- AbstractBeanFactory :  parentBeanFactory.doGetBean
          4.2- args != null : parentBeanFactory.getBean(nameToLookup, args)
              ?- 使用顯式參數委托給父類(lèi)
          4.3- requiredType != null: parentBeanFactory.getBean(nameToLookup, requiredType)
              ?- 委托給標準的getBean方法
          4.4- 都不符合 : parentBeanFactory.getBean(nameToLookup)
              ?- Pro2
              
          // 這里直接返回是因為存在父 BeanFactory , 且存在 BeanDefinition , 這就意味著(zhù)ParentBeanFactory 能處理 , 基于 Pro 1 的原因 , 選擇直接返回 
              
              
          // Pro 1 :  為什么從父工廠(chǎng)里面獲取 -> BeanFactory parentBeanFactory = getParentBeanFactory();
          這是一個(gè)遞歸操作 , 也是仿照雙親委派的方式來(lái)處理 , 即先有父對象來(lái)加載對應的對象
          
          同樣的 , 當進(jìn)入 doGet 的時(shí)候 , 默認通過(guò)父方法去加載 , 如果父方法處理完成了 , 即加載出 Bean 了 , 就直接返回
          好處呢 , 想了一下 , 可以保證每個(gè)實(shí)現能專(zhuān)注于其本身需要處理的 Bean , 而不需要關(guān)注原本就會(huì )加載的 Bean 
          回顧一下雙親委派的目的 : 避免重復加載 + 避免核心類(lèi)篡改    
              
          // 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 對于只檢查的那樣處理有什么目的 ?

              
          這里如果是只檢查而無(wú)需創(chuàng  )建 , 會(huì )在 markBeanAsCreated 方法中做2件事
          clearMergedBeanDefinition(beanName);
          this.alreadyCreated.add(beanName);    
          
          這樣的目的是為了即標注方法已經(jīng)檢查成功 , 而避免走沒(méi)必要的反復流程 ,允許bean工廠(chǎng)為重復創(chuàng  )建指定bean而優(yōu)化其緩存 
          --> 實(shí)際邏輯    
          
          // Step 1 : alreadyCreated 是什么 ?
          Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
              ?- alreadyCreated 包含 至少已經(jīng)創(chuàng  )建過(guò)一次的bean的名稱(chēng)的 Set 集合
          
          // Step 2 : 如何利用這個(gè)對象 ?
          1 : AbstractAutowireCapableBeanFactory # getTypeForFactoryBean
              ?- 這里會(huì )通過(guò)這個(gè)對象校驗引用的工廠(chǎng)bean還不存在,那么在這里退出——不會(huì )僅僅為了獲取FactoryBean的對象類(lèi)型而強制創(chuàng  )建另一個(gè)bean
              
          2 : clearMetadata 時(shí) , 需要判斷是否為空
          
           
          
          

          PS:M171_02_05 三種不同方式的本質(zhì)區別 ?

          相同點(diǎn) :  最終調用 getObjectForBeanInstance    
          5.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
              - 首先通過(guò) getSingleton 方法, 保證加載的唯一性
              - 回調 createBean 創(chuàng  )建 Bean
              - 通過(guò) getObjectForBeanInstance 實(shí)例化真正的 Bean
              
          5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation  + getObjectForBeanInstance
              - 仔細看就能發(fā)現 , 沒(méi)有相關(guān)的 scope 對象控制 , 直接進(jìn)行創(chuàng  )建
              
          5.3- 其他 : 主要是通過(guò) Scope 控制域 + Prototype 流程
              - 它是 singleton 的結合體 , 
              - 首先會(huì )準備一個(gè) Scope 對象用于控制 Scope 域內的 Bean 情況
              - 再調用和 Prototype 一致的流程進(jìn)行創(chuàng  )建
                  
          
          

          PS:M171_02_06 sharedInstance 和 bean 的區別

          這里可以看到 , 首先通過(guò) createBean 創(chuàng )建了一個(gè) Object 對象 sharedInstance , 又通過(guò) getObjectForBeanInstance 生成了一個(gè) Bean ,他們有什么本質(zhì)的區別 ?

          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 的工廠(chǎng)了 , 一般情況下 , createBean 創(chuàng  )建的 Bean 就是一個(gè) 完整的 Bean
          // 但是 ,如果它是一個(gè)FactoryBean,需要使用它來(lái)創(chuàng  )建一個(gè)bean實(shí)例,除非調用者實(shí)際上想要一個(gè)對工廠(chǎng)的引用。
          
          

          sharedInstance 中的 Bean 是已經(jīng)走完 Bean 創(chuàng )建流程的 Bean了

          2.1.3 AbstractBeanFactory # createBean

          C171- AbstractBeanFactory 
          	M171_03- createBean(String beanName, RootBeanDefinition mbd, Object[] args) 
                      P- mbd :  BeanDefinition 對象 , 已經(jīng)合并了父類(lèi)屬性
                      p- args : 用于構造函數或者工廠(chǎng)方法創(chuàng  )建 Bean 實(shí)例對象的參數
          
          

          2.1.4 AbstractAutowireCapableBeanFactory # createBean 主流程

          C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
              M173_02- createBean(String beanName, RootBeanDefinition mbd,Object[] args)
                  ?- M170_01 方法的默認實(shí)現
                  LV173_02_01- RootBeanDefinition mbdToUse : 內部屬性 , 用于標識根 BeanDefinition 
                  1- Class<?> resolvedClass = resolveBeanClass(mbd, beanName) -> PS:M173_02_01
                      ?- 解析獲得指定 BeanDefinition 的 class 屬性 -> M173_04
                  IF- 解析的 Class 不為 null , 且存在 BeanClass 和 BeanClassName
                      - 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) --- 實(shí)例化的前置處理 
                  - 如果 bean 不為 null , 則直接返回 (直接返回是因為上一步生成了一個(gè)代理類(lèi) ,AOP )
                  4- Object beanInstance = doCreateBean(beanName, mbdToUse, args); --- 創(chuàng  )建對象
              M173_03- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
              M173_04- resolveBeanClass : 將bean類(lèi)名解析為class引用  
              
              
              
          // PS:M173_02_01 RootBeanDefinition 
          // 確保bean類(lèi)在此時(shí)被實(shí)際解析,如果動(dòng)態(tài)解析的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- 如果沒(méi)有對應方法 ,拋出 BeanDefinitionValidationException 
                  3- 如果 count = 1 , 將 Overloaded 標記為未重載 , 在后續調用的時(shí)候,可以直接找到方法而不需要進(jìn)行方法參數的校驗
          
          
          // M173_02 源碼簡(jiǎn)介
          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) : 創(chuàng  )建 Bean 對象
                  ?- 非代理對象的 常規Bean 創(chuàng  )建 , 主要節點(diǎn)有以下幾個(gè)
                  - 準備 BeanWrapper : BeanWrapper 是對 Bean 的包裝
                  - 如果單例模型,則從未完成的 FactoryBean 緩存中刪除
                  - createBeanInstance(beanName, mbd, args) : 進(jìn)入Bean 創(chuàng  )建流程 , 創(chuàng  )建一個(gè) Bean 的封裝 BeanWrapper 
                      ?- 這里的獲取如果是單例 , 則直接獲取 , 并且移除緩存中的對象 
                      ?- 否則調用 createBeanInstance 獲取
                  - instanceWrapper.getWrappedInstance();
                      ?- 包裝的實(shí)例對象
                  - instanceWrapper.getWrappedClass();
                      ?- 包裝的實(shí)例對象的類(lèi)型
              	IF- applyMergedBeanDefinitionPostProcessors
                      ?- 如果有后置處理 , 則在此處進(jìn)行后置處理 , synchronized 上鎖
              	IF- addSingletonFactory 
                      ?- 如果是單例 , 且允許+ 存在循環(huán)依賴(lài) , 則在此處進(jìn)行單例模式的處理
              	- populateBean : 屬性注入操作 -> M173_30
              	- initializeBean : 初始化 Bean 
                      ?- 此處會(huì )進(jìn)行 Init-Method 的處理 ->  PS:M173_05_03
              	IF- getSingleton 
                      ?- 循環(huán)依賴(lài)情況 , 則會(huì )遞歸初始依賴(lài) bean , 此處返回的是一個(gè)用于循環(huán)處理的空對象
                      ?- 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 : 根據屬性名稱(chēng),完成自動(dòng)依賴(lài)注入
              M173_11- autowireByType : 根據屬性類(lèi)型,完成自動(dòng)依賴(lài)注入
                  - resolveDependency -> resolveDependency
              M173_12- resolveDependency : 完成了所有注入屬性的獲取
                  - doResolveDependency
              M173_13- doResolveDependency	
              M173_15- applyPropertyValues : 應用到已經(jīng)實(shí)例化的 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 , 并且通過(guò) 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) : 依賴(lài)檢查
                  - Step 7 : this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs) : 
              - this.initializeBean(beanName, exposedObject, mbd);
              - this.registerDisposableBeanIfNecessary(beanName, bean, mbd);     
              
              
          // 附錄 : M173_05 doCreateBean 源碼比較長(cháng) ,放在結尾
          

          PS:M173_05_01 : 遞歸循環(huán)細說(shuō)

          在 doCreateBean 中 , 會(huì )對循環(huán)依賴(lài)進(jìn)行處理
          
          // 循環(huán)依賴(lài)情況 , 則會(huì )遞歸初始依賴(lài) bean , 此處返回的是一個(gè)用于循環(huán)處理的空對象
          // 2種情況 , 返回早期對象或者 getDependentBeans 遞歸所有的
          if (earlySingletonExposure) {
              // 參考循環(huán)依賴(lài)那一章 , 這里可能會(huì )返回一個(gè)未完善的前置對象引用
              // 只有存在循環(huán)依賴(lài) , 這里才不會(huì )為空
              Object earlySingletonReference = getSingleton(beanName, false);
              if (earlySingletonReference != null) {
                  if (exposedObject == bean) {
                      exposedObject = earlySingletonReference;
                  // 判斷存在循環(huán)依賴(lài)    
                  }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                      // 返回依賴(lài)于指定bean的所有bean的名稱(chēng)(如果有的話(huà))
                      String[] dependentBeans = getDependentBeans(beanName);
                      Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                      for (String dependentBean : dependentBeans) {
                          // 如果有被用于類(lèi)型檢查之外的其他目的時(shí) ,則不可以刪除 -> PS:M173_05_03
                          if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                              // 無(wú)需刪除 , 則添加
                              actualDependentBeans.add(dependentBean);
                          }
                      }
                      // 因為上文添加 , 這里就形成依賴(lài)
                      if (!actualDependentBeans.isEmpty()) {
                          throw new BeanCurrentlyInCreationException(".....");
                      }
                  }
              }
          }
          
          // PS:M173_05_03 : 什么是其他的目的 ? 
          removeSingletonIfCreatedForTypeCheckOnly 核心是校驗 alreadyCreated 
          1 . 如果 alreadyCreated 已經(jīng)存在了 ,則說(shuō)明對應的對象已經(jīng)創(chuàng  )建完成了 
          2 . 如果對應的對象已經(jīng)創(chuàng  )建完了了 , 其中依賴(lài)的當前對象不是正在創(chuàng  )建的對象
          3 . 但是其中的屬性又不是當前的對象 , 說(shuō)明循環(huán)依賴(lài)不成立 , 依賴(lài)已經(jīng)串了
          
          @ 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) {
                      // 進(jìn)入Bean 創(chuàng  )建流程 , 創(chuàng  )建一個(gè) Bean 的封裝 BeanWrapper 
                      instanceWrapper = createBeanInstance(beanName, mbd, args);
                  }
                  // 獲取包裝的實(shí)例對象
                  final Object bean = instanceWrapper.getWrappedInstance();
                  // 包裝的實(shí)例對象的類(lèi)型
                  Class<?> beanType = instanceWrapper.getWrappedClass();
                  if (beanType != NullBean.class) {
                      mbd.resolvedTargetType = beanType;
                  }
          
                  //  Step 2 : 如果有后置處理 , 則在此處進(jìn)行后置處理 , synchronized 上鎖
                  synchronized (mbd.postProcessingLock) {
                      if (!mbd.postProcessed) {
                          try {
                              applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                          }
                          catch (Throwable ex) {
                              throw new BeanCreationException("....");
                          }
                          mbd.postProcessed = true;
                      }
                  }
          
                  // Step 3 :如果是單例 , 且允許+ 存在循環(huán)依賴(lài) , 則在此處進(jìn)行單例模式的處理
                  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                          isSingletonCurrentlyInCreation(beanName));
                  if (earlySingletonExposure) {
          
                      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
                  }
          
                  // Step 4 : 此處會(huì )進(jìn)行 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("....");
                      }
                  }
              
              
                  // 循環(huán)依賴(lài)情況 , 則會(huì )遞歸初始依賴(lài) bean , 此處返回的是一個(gè)用于循環(huán)處理的空對象
                  // 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;
              }
          
          

          總結

          其中有幾個(gè)錨點(diǎn) :

          Step 1 : 入口

          入口中主要是會(huì )統籌管理 , 如果緩存中有 , 則直接使用 , 如果沒(méi)有 , 則區別 Scope 分別使用不同的方式獲取一個(gè) Bean

          - C171- AbstractBeanFactory 
              - M171_02- doGetBean  
          
          

          Step 2 : 創(chuàng )建主流程

          創(chuàng )建主流程就是創(chuàng )建一個(gè)完整的 Bean , 走一個(gè) Bean 創(chuàng )建的完整周期 , 包括 process , 屬性注入 , init 初始化等等 , 這些我們在后面的文章中再詳細說(shuō)說(shuō)

          // 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;
                  
                  // 單例方式獲取一個(gè) Bean , 循環(huán)依賴(lài)就是這個(gè)環(huán)節處理 -> -> PS:M171_02_02 
                  Object sharedInstance = getSingleton(beanName);
                  if (sharedInstance != null && args == null) {
                      // 直接從實(shí)例化中獲取 Bean
                      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
                  }
          
                  else {
                      // 階段二 : 單例緩存中獲取失敗后 
                      if (isPrototypeCurrentlyInCreation(beanName)) {
                          //  如果是原型模式且存在循環(huán)依賴(lài)則拋出異常
                          throw new BeanCurrentlyInCreationException(beanName);
                      }
          
                      // 檢查這個(gè)工廠(chǎng)中是否存在bean定義
                      BeanFactory parentBeanFactory = getParentBeanFactory();
                      
                      //  如果工廠(chǎng)中已經(jīng)存在了 , 會(huì )有四種情況會(huì )直接 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);
                          }
                      }
          
                      //  如果為類(lèi)型檢查而獲取實(shí)例,而不是實(shí)際使用 , 則將指定的bean標記為已經(jīng)創(chuàng  )建 -> PS:M171_02_04
                      if (!typeCheckOnly) {
                          markBeanAsCreated(beanName);
                      }
          
                      try {
                          // RootBeanDefinition的獲取和檢查  LV171_001
                          final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                          checkMergedBeanDefinition(mbd, beanName, args);
          
                          // 階段三 : 依賴(lài)檢查 , 保證初始化當前bean所依賴(lài)的bean
                          // 對于屬性 LV171_001:mbd , 通過(guò) getDependsOn 獲取所有依賴(lài)
                          String[] dependsOn = mbd.getDependsOn();
                          if (dependsOn != null) {
                              //  循環(huán)所有的依賴(lài) , 分別調用 registerDependentBean + getBean 進(jìn)行遞歸操作
                              for (String dep : dependsOn) {
                                  if (isDependent(beanName, dep)) {
                                      throw new BeanCreationException(.....);
                                  }
                                  registerDependentBean(dep, beanName);
                                  try {
                                      getBean(dep);
                                  }
                                  catch (NoSuchBeanDefinitionException ex) {
                                      throw new BeanCreationException(.....);
                                  }
                              }
                          }
          
                          // 階段四 : 三種不同的類(lèi)型獲得 Bean 實(shí)例
                          // 判斷 Bean 的類(lèi)型不同創(chuàng  )建 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;
                      }
                  }
          
                  // 階段五 : 此時(shí) Bean 已經(jīng)準備完成了 , 此處檢查所需的類(lèi)型是否與實(shí)際bean實(shí)例的類(lèi)型匹配
                  // 如果實(shí)例不匹配 , 則需要轉換, 轉換后直接返回
                  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());
                      }
                  }
                  // 如果上面沒(méi)有返回 , 則直接發(fā)返回原本的Bean 
                  return (T) bean;
              }
          
          

          參考與感謝

          寫(xiě)這個(gè)之前 , 還跑過(guò)去再讀了一遍 , 很感謝死磕系列開(kāi)啟了 IOC 的源碼學(xué)習

          以上就是Spring IOC:CreateBean環(huán)節中的流程轉換的詳細內容,更多關(guān)于Spring IOC CreateBean的資料請關(guān)注腳本之家其它相關(guān)文章!

          免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

          边摸边脱吃奶边高潮视频免费| 巨大黑人极品VIDEOS精品| 国产A级毛片| 一色屋精品视频在线观看免费| 成熟丰满熟妇高潮XXXXX| 欧美交换配乱吟粗大25P|