真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Bean的獲取過(guò)程是什么

本篇內(nèi)容主要講解“Bean的獲取過(guò)程是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Bean的獲取過(guò)程是什么”吧!

創(chuàng)新互聯(lián)公司云計(jì)算的互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)13年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、雅安服務(wù)器托管、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn),已先后獲得國(guó)家工業(yè)和信息化部頒發(fā)的互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)許可證。專(zhuān)業(yè)提供云主機(jī)、雅安服務(wù)器托管、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。

目錄

  • 一、前言

  • 二、面試題

  • 三、Bean 的獲取過(guò)程

    • 1. getBean 核心流程圖

    • 2. getBean 從哪開(kāi)始讀源碼

    • 3. getBean 源碼全局預(yù)覽

    • 4. beanName 轉(zhuǎn)換操作

    • 5. depends-on 依賴(lài) Bean

    • 6. 處理單實(shí)例 Bean

    • 7. 從緩存中獲取 bean 實(shí)例

    • 8. FactoryBean 中獲取 bean 實(shí)例

  • 四、測(cè)試案例

    • 1. 別名

    • 2. 依賴(lài)

    • 3. BeanFactory

一、前言

你提出問(wèn)題,就要給出解決方案!

最近有粉絲小伙伴反饋,與自己的上級(jí)溝通總是遇到障礙,感覺(jué)不被理解。大部分時(shí)候他提出來(lái)的事情都可能會(huì)被領(lǐng)導(dǎo)說(shuō):“我沒(méi)get到你的點(diǎn)”、“你想做的這個(gè)項(xiàng)目沒(méi)有業(yè)務(wù)價(jià)值”、“你提出問(wèn)題,就要給出解決方案”,等等諸如此類(lèi)的回答。

鑒于具體情況要具體分析,可能我們并不一定能判斷出是誰(shuí)的問(wèn)題,導(dǎo)致在每次的交談中出現(xiàn)的分歧??赡苁莑eader有l(wèi)eader的苦衷和視角,也可能是員工有員工的理解和想法,所以最終沒(méi)有達(dá)成一致。

但就帶團(tuán)隊(duì)來(lái)講,有效溝通很重要。就像:如果你說(shuō)的都對(duì),那我為什么和你爭(zhēng)吵呢?與其壓制遇到的矛盾點(diǎn),不如都攤開(kāi)了聊,誰(shuí)的視角和心胸更大,誰(shuí)就多有一些同理心。


如果尖銳的批評(píng)完全消失,溫和的批評(píng)將會(huì)變得刺耳。

如果溫和的批評(píng)也不被允許,沉默將被認(rèn)為居心叵測(cè)。

如果沉默也不再允許,贊揚(yáng)不夠賣(mài)力將是一種罪行。

如果只允許一種聲音存在,那么,唯一存在的那個(gè)聲音就是謊言。

 

二、面試題

謝飛機(jī),小記!,總感覺(jué) Spring 也沒(méi)啥看的,怎么面試官一問(wèn)就能問(wèn)出花?

面試官:Spring 的 getBean 中,transformedBeanName 的作用是什么?

謝飛機(jī):不知道呀,看單詞意思好像是改變Bean名稱(chēng)。

面試官:那這么說(shuō),你的 Bean 如果有 alias 別名,Spring 在獲取 Bean 時(shí)候要怎么處理?

謝飛機(jī):這!

面試官:那如果用了 depends-on 呢?

謝飛機(jī):啊, 我沒(méi)用過(guò) depends-on 我不知道!

面試官:那你調(diào)試代碼時(shí)候,看見(jiàn)過(guò)BeanName前面有 & 的情況嗎,為啥會(huì)出現(xiàn)?

謝飛機(jī):我不配知道!再見(jiàn)!

 

三、Bean 的獲取過(guò)程

對(duì)于剛接觸看 Spring 源碼的伙伴來(lái)說(shuō),可能很疑惑于怎么就獲取一個(gè) Bean 就這么多流程呢?

  • 可能有 Bean 可能有別名、可能有依賴(lài)、也可能是被 FactoryBean 包裝過(guò),所以會(huì)有 transformedBeanName 來(lái)處理這些差異化行為。
  • 有沒(méi)有循環(huán)依賴(lài)、有沒(méi)有父工廠(chǎng)、是單例還是原型、是懶加載還是預(yù)加載、在不在緩沖區(qū),所以就有各種組合判斷來(lái)做不同的流程。
  • 提早暴漏對(duì)象、三級(jí)緩存、后置標(biāo)記清楚,所有的優(yōu)化處理都是為了讓整個(gè) Bean 的獲取更加高效。

所以,它為了適應(yīng)各類(lèi)的需求,變得越來(lái)越復(fù)雜了。而這部分知識(shí)的深入學(xué)習(xí)絕對(duì)不只是為了應(yīng)付八股文,更多的是考慮到在日常的 Spring 使用中遇到復(fù)雜問(wèn)題時(shí)有沒(méi)有一個(gè)大致知曉的流程,可以快速定位問(wèn)題,以及此類(lèi)需求的技術(shù)實(shí)現(xiàn)方案是否能在以后的應(yīng)用開(kāi)發(fā)中起到一定的指導(dǎo)作用,因?yàn)樗且环N設(shè)計(jì)方案的具體實(shí)現(xiàn)。

 

1. getBean 核心流程圖

Bean的獲取過(guò)程是什么  
小傅哥,getBean 核心流程圖
  • 整張圖就是 getBean 過(guò)程中涉及到的類(lèi)和核心流程用到的方法以及操作的內(nèi)容。如果你能把整張圖全理解了,那么基本也就看懂了 getBean 的全過(guò)程。
  • 本張圖可能會(huì)因?yàn)榫W(wǎng)絡(luò)壓縮變得不清晰,可以通過(guò)     關(guān)注公眾號(hào):bugstack蟲(chóng)洞棧,回復(fù):     圖稿,獲取。

接下來(lái),我們就依次的把關(guān)于獲取 Bean 實(shí)例的重點(diǎn)代碼列舉出來(lái)做分析,讀者伙伴也可以結(jié)合流程圖一起看,這樣會(huì)更方便理解。

 

2. getBean 從哪開(kāi)始讀源碼

@Test
public void test_getBean() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
    UserDao userDao = beanFactory.getBean("userDao", UserDao.class);
    logger.info("獲取 Bean:{}", userDao);
}
 
  • 在日常應(yīng)用到 Spring 的開(kāi)發(fā)中基本都是基于注解,幾乎不會(huì)自己去使用     beanFactory.getBean 的方式去獲取一個(gè) Bean 實(shí)例。
  • 所以在你學(xué)習(xí)的時(shí)候如果找不到查看 getBean 源碼的入口,也不方便調(diào)試熟悉源碼時(shí),可以寫(xiě)這樣一個(gè)單元測(cè)試類(lèi),點(diǎn)入到 getBean 就可以閱讀源碼了。
 

3. getBean 源碼全局預(yù)覽

源碼位置:AbstractBeanFactory -> getBean() -> doGetBean()

@Override
public  T getBean(String name, Class requiredType) throws BeansException { 
    // getBean 就像你的領(lǐng)導(dǎo)其實(shí)沒(méi)做啥,都在 doGetBean 里
 return doGetBean(name, requiredType, null, false);
}
 
protected  T doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
  throws BeansException {     
    
    // 處理別名BeanName、處理帶&符的工廠(chǎng)BeanName
 final String beanName = transformedBeanName(name);
 Object bean;  

 // 先嘗試從緩存中獲取Bean實(shí)例,這個(gè)位置就是三級(jí)緩存解決循環(huán)依賴(lài)的方法
 Object sharedInstance = getSingleton(beanName);   

 if (sharedInstance != null && args == null) {
  if (logger.isDebugEnabled()) {
   if (isSingletonCurrentlyInCreation(beanName)) {
    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
      "' that is not fully initialized yet - a consequence of a circular reference");
   }
   else {
    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
   }
  }        
        
        // 1. 如果 sharedInstance 是普通的 Bean 實(shí)例,則下面的方法會(huì)直接返回
        // 2. 如果 sharedInstance 是工廠(chǎng)Bean類(lèi)型,則需要獲取 getObject 方法,可以參考關(guān)于 FactoryBean 的實(shí)現(xiàn)類(lèi) 
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 }
 else {
  
        // 循環(huán)依賴(lài)有三種,setter注入、多實(shí)例和構(gòu)造函數(shù),Spring 只能解決 setter 注入,所以這里是 Prototype 則會(huì)拋出異常
  if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
  }    

  // 1. 父 bean 工廠(chǎng)存在
        // 2. 當(dāng)前 bean 不存在于當(dāng)前bean工廠(chǎng),則到父工廠(chǎng)查找 bean 實(shí)例
  BeanFactory parentBeanFactory = getParentBeanFactory();
  if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   // 獲取 name 對(duì)應(yīng)的 beanName,如果 name 是以 & 開(kāi)頭,則返回 & + beanName
   String nameToLookup = originalBeanName(name);         
            
            // 根據(jù) args 參數(shù)是否為空,調(diào)用不同的父容器方法獲取 bean 實(shí)例
   if (args != null) {
    return (T) parentBeanFactory.getBean(nameToLookup, args);
   }
   else {
    return parentBeanFactory.getBean(nameToLookup, requiredType);
   }
  }       

        // 1. typeCheckOnly,用于判斷調(diào)用 getBean 方法時(shí),是否僅是做類(lèi)型檢查
        // 2. 如果不是只做類(lèi)型檢查,就會(huì)調(diào)用 markBeanAsCreated 進(jìn)行記錄
  if (!typeCheckOnly) {
   markBeanAsCreated(beanName);
  }
  try {    
    
            // 從容器 getMergedLocalBeanDefinition 獲取 beanName 對(duì)應(yīng)的 GenericBeanDefinition,轉(zhuǎn)換為 RootBeanDefinition
   final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 
            // 檢查當(dāng)前創(chuàng)建的 bean 定義是否為抽象 bean 定義
   checkMergedBeanDefinition(mbd, beanName, args);
   
            // 處理使用了 depends-on 注解的依賴(lài)創(chuàng)建 bean 實(shí)例
   String[] dependsOn = mbd.getDependsOn();
   if (dependsOn != null) {
    for (String dep : dependsOn) {   
                    // 監(jiān)測(cè)是否存在 depends-on 循環(huán)依賴(lài),若存在則會(huì)拋出異常
     if (isDependent(beanName, dep)) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
     }       
                    
                    // 注冊(cè)依賴(lài)記錄
     registerDependentBean(dep, beanName);
     try {    
         // 加載 depends-on 依賴(lài)(dep 是 depends-on 縮寫(xiě))
      getBean(dep);
     }
     catch (NoSuchBeanDefinitionException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
     }
    }
   }  

   // 創(chuàng)建單例 bean 實(shí)例
   if (mbd.isSingleton()) {    

       // 把 beanName 和 new ObjectFactory 匿名內(nèi)部類(lèi)傳入回調(diào)
    sharedInstance = getSingleton(beanName, new ObjectFactory() {
     @Override
     public Object getObject() throws BeansException {
      try {    
                            // 創(chuàng)建 bean
       return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
       // 創(chuàng)建失敗則銷(xiāo)毀
       destroySingleton(beanName);
       throw ex;
      }
     }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
   }      
            // 創(chuàng)建其他類(lèi)型的 bean 實(shí)例
   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, new ObjectFactory() {
      @Override
      public Object getObject() throws BeansException {
       beforePrototypeCreation(beanName);
       try {
        return createBean(beanName, mbd, args);
       }
       finally {
        afterPrototypeCreation(beanName);
       }
      }
     });
     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;
  }
 }
 // 如果需要類(lèi)型轉(zhuǎn)換,這里會(huì)進(jìn)行操作
 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
  try {
   return getTypeConverter().convertIfNecessary(bean, requiredType);
  }
  catch (TypeMismatchException ex) {
   if (logger.isDebugEnabled()) {
    logger.debug("Failed to convert bean '" + name + "' to required type '" +
      ClassUtils.getQualifiedName(requiredType) + "'", ex);
   }
   throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  }
 }    

    // 返回 Bean
 return (T) bean;
}
 

綜上基本就是 getBean 過(guò)程涉及到的核心處理方法,基本包括;

  • transformedBeanName,處理別名BeanName、處理帶&符的工廠(chǎng)BeanName。
  • getSingleton,先嘗試從緩存中獲取Bean實(shí)例,這個(gè)位置就是三級(jí)緩存解決循環(huán)依賴(lài)的方法。
  • getObjectForBeanInstance,如果 sharedInstance 是普通的 Bean 實(shí)例,則下面的方法會(huì)直接返回。另外 sharedInstance 是工廠(chǎng)Bean類(lèi)型,則需要獲取 getObject 方法,可以參考關(guān)于 FactoryBean 的實(shí)現(xiàn)類(lèi)。
  • isPrototypeCurrentlyInCreation,循環(huán)依賴(lài)有三種,setter注入、多實(shí)例和構(gòu)造函數(shù),Spring 只能解決 setter 注入,所以這里是 Prototype 則會(huì)拋出異常。
  • getParentBeanFactory,父 bean 工廠(chǎng)存在,當(dāng)前 bean 不存在于當(dāng)前bean工廠(chǎng),則到父工廠(chǎng)查找 bean 實(shí)例。
  • originalBeanName,獲取 name 對(duì)應(yīng)的 beanName,如果 name 是以 & 開(kāi)頭,則返回 & + beanName
  • args != null,根據(jù) args 參數(shù)是否為空,調(diào)用不同的父容器方法獲取 bean 實(shí)例
  • !typeCheckOnly,typeCheckOnly,用于判斷調(diào)用 getBean 方法時(shí),是否僅是做類(lèi)型檢查,如果不是只做類(lèi)型檢查,就會(huì)調(diào)用 markBeanAsCreated 進(jìn)行記錄
  • mbd.getDependsOn,處理使用了 depends-on 注解的依賴(lài)創(chuàng)建 bean 實(shí)例
  • isDependent,監(jiān)測(cè)是否存在 depends-on 循環(huán)依賴(lài),若存在則會(huì)拋出異常
  • registerDependentBean,注冊(cè)依賴(lài)記錄
  • getBean(dep),加載 depends-on 依賴(lài)(dep 是 depends-on 縮寫(xiě))
  • mbd.isSingleton(),創(chuàng)建單例 bean 實(shí)例
  • mbd.isPrototype(),創(chuàng)建其他類(lèi)型的 bean 實(shí)例
  • return (T) bean,返回 Bean 實(shí)例
 

4. beanName 轉(zhuǎn)換操作

處理 & 符:transformedBeanName() -> BeanFactoryUtils.transformedBeanName(name)

public static String transformedBeanName(String name) {
 Assert.notNull(name, "'name' must not be null");
 String beanName = name;
 while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
  beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
 }
 return beanName;
}
 
  • 使用 FactoryBean 創(chuàng)建出的對(duì)象,會(huì)在 DefaultListableBeanFactory 初始化的時(shí)候,使用 getBean(FACTORY_BEAN_PREFIX + beanName) 給 beanName 加上 &     (String FACTORY_BEAN_PREFIX = "&")
  • 這里是使用 while 循環(huán)逐步的把 & 去掉,只要截取首個(gè)字符是 & 符,就繼續(xù)循環(huán)截取。     &&&userService -> &&userService -> &userService -> userService

別名轉(zhuǎn)換:transformedBeanName() -> canonicalName

public String canonicalName(String name) {
 String canonicalName = name;
 // Handle aliasing...
 String resolvedName;
 do {
  resolvedName = this.aliasMap.get(canonicalName);
  if (resolvedName != null) {
   canonicalName = resolvedName;
  }
 }
 while (resolvedName != null);
 return canonicalName;
}
 



 
  • 首先 Spring 對(duì) Bean 的存放并不會(huì)使用別名作為Map中的key,所以遇到所有別名獲取 Bean 都需要查到對(duì)應(yīng)原來(lái)名字,才可以。     如果你知道這個(gè)事,是不遇到此類(lèi)問(wèn)題時(shí),就知道從哪下手查了
  • do...while 循環(huán)會(huì)依次像鏈條一樣不斷的尋找別名對(duì)應(yīng)的名稱(chēng),直到當(dāng)前這個(gè)名稱(chēng)沒(méi)有別名了,就返回對(duì)應(yīng) BeanName
 

5. depends-on 依賴(lài) Bean

AbstractBeanFactory -> isDependent(beanName, dep) -> DefaultSingletonBeanRegistry

protected boolean isDependent(String beanName, String dependentBeanName) {
 synchronized (this.dependentBeanMap) {
  return isDependent(beanName, dependentBeanName, null);
 }
 



 
  • isDependent 處理的是使用了 depends-on 配置的 Bean 定義。
private boolean isDependent(String beanName, String dependentBeanName, Set alread
 if (alreadySeen != null && alreadySeen.contains(beanName)) {
  return false;
 }
 String canonicalName = canonicalName(beanName);
 Set dependentBeans = this.dependentBeanMap.get(canonicalName);
 if (dependentBeans == null) {
  return false;
 }
 if (dependentBeans.contains(dependentBeanName)) {
  return true;
 }
 for (String transitiveDependency : dependentBeans) {
  if (alreadySeen == null) {
   alreadySeen = new HashSet();
  }
  alreadySeen.add(beanName);
  if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
   return true;
  }
 }
 return false;
}
 
  • alreadySeen != null,監(jiān)測(cè)已經(jīng)依賴(lài)的 Bean
  • canonicalName,處理別名配置,找到最原來(lái)是的 BeanName
  • SetdependentBeans,獲取依賴(lài)的 Bean 集合
  • for 循環(huán)遞歸檢測(cè)依賴(lài)的 Bean,并添加到 alreadySeen 中

AbstractBeanFactory -> registerDependentBean(dep, beanName) -> DefaultSingletonBeanRegistry

public void registerDependentBean(String beanName, String dependentBeanName) {
 String canonicalName = canonicalName(beanName);  

 synchronized (this.dependentBeanMap) {
  Set dependentBeans = this.dependentBeanMap.get(canonicalName);
  if (dependentBeans == null) {
   dependentBeans = new LinkedHashSet(8);
   this.dependentBeanMap.put(canonicalName, dependentBeans);
  }
  dependentBeans.add(dependentBeanName);
 }   

 synchronized (this.dependenciesForBeanMap) {
  Set dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName
  if (dependenciesForBean == null) {
   dependenciesForBean = new LinkedHashSet(8);
   this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
  }
  dependenciesForBean.add(canonicalName);
 }
}
 
  • canonicalName(beanName),獲取原始的 beanName
  • synchronized (this.dependentBeanMap),添加 到 dependentBeanMap 中
  • synchronized (this.dependenciesForBeanMap),添加 到 dependenciesForBeanMap 中

最后:getBean(dep),就可以獲取到 depends-on 依賴(lài)的 Bean 了

 

6. 處理單實(shí)例 Bean

AbstractBeanFactory -> mbd.isSingleton()

if (mbd.isSingleton()) {
 sharedInstance = getSingleton(beanName, new ObjectFactory() {
  @Override
  public Object getObject() throws BeansException {
   try {
    return createBean(beanName, mbd, args);
   }
   catch (BeansException ex) {
    destroySingleton(beanName);
    throw ex;
   }
  }
 });
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
 
  • 這一部分是使用 beanName 和 singletonFactory 匿名內(nèi)部類(lèi)傳入等待回調(diào)的方式創(chuàng)建單實(shí)例 Bean 實(shí)例
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
 Assert.notNull(beanName, "'beanName' must not be null");
 synchronized (this.singletonObjects) {
  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 + "'");
   }
   beforeSingletonCreation(beanName);
   boolean newSingleton = false;
   boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
   if (recordSuppressedExceptions) {
    this.suppressedExceptions = new LinkedHashSet();
   }
   try {
    singletonObject = singletonFactory.getObject();
    newSingleton = true;
   }
   catch (IllegalStateException ex) {
    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;
    }
    afterSingletonCreation(beanName);
   }
   if (newSingleton) {
    addSingleton(beanName, singletonObject);
   }
  }
  return (singletonObject != NULL_OBJECT ? singletonObject : null);
 }
}
 
  • this.singletonObjects.get(beanName),先嘗試從緩存池中獲取對(duì)象,沒(méi)有就繼續(xù)往下執(zhí)行
  • beforeSingletonCreation(beanName),標(biāo)記當(dāng)前 bean 被創(chuàng)建,如果有構(gòu)造函數(shù)注入的循環(huán)依賴(lài)會(huì)報(bào)錯(cuò)
  • singletonObject = singletonFactory.getObject(),創(chuàng)建 bean 過(guò)程就是調(diào)用 createBean() 方法
  • afterSingletonCreation(beanName),最后把標(biāo)記從集合中移除
  • addSingleton(beanName, singletonObject),新創(chuàng)建的會(huì)加入緩存集合
 

7. 從緩存中獲取 bean 實(shí)例

doCreateBean -> if (earlySingletonExposure) -> getSingleton(beanName, false)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 從 singletonObjects 獲取實(shí)例,singletonObjects 中緩存的實(shí)例都是完全實(shí)例化好的 bean,可以直接使用
 Object singletonObject = this.singletonObjects.get(beanName);
    // 如果 singletonObject 為空,則沒(méi)有創(chuàng)建或創(chuàng)建中
 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 加鎖
  synchronized (this.singletonObjects) {
            // 單例緩存池中,沒(méi)有當(dāng)前beanName
   singletonObject = this.earlySingletonObjects.get(beanName);
   if (singletonObject == null && allowEarlyReference) {
    ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
    if (singletonFactory != null) {
                    // 加入到三級(jí)緩存,暴漏早期對(duì)象用于解決三級(jí)緩存
     singletonObject = singletonFactory.getObject();  
     this.earlySingletonObjects.put(beanName, singletonObject);
     this.singletonFactories.remove(beanName);
    }
   }
  }
 }
 return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
 
  • 其實(shí)這一段代碼主要就是使用三級(jí)緩存解決set注入循環(huán)依賴(lài)的,后面會(huì)單獨(dú)列一個(gè)章節(jié)對(duì)循環(huán)依賴(lài)做相關(guān)實(shí)驗(yàn)驗(yàn)證
  • singletonObjects,用于存放初始化好的 bean 實(shí)例。
  • earlySingletonObjects,用于存放初始化中的 bean,來(lái)解決循環(huán)依賴(lài)。
  • singletonFactories,用于存放 bean 工廠(chǎng),bean 工廠(chǎng)所生成的 bean 還沒(méi)有完成初始化 bean。
 

8. FactoryBean 中獲取 bean 實(shí)例

AbstractBeanFactory -> getObjectForBeanInstance(sharedInstance, name, beanName, null)

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    
    // 如果 beanName 以 & 開(kāi)頭,但 beanInstance 卻不是 FactoryBean,則會(huì)拋出異常
 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
  throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
 }

    // 這里判斷就是這個(gè) bean 是不是 FactoryBean,不是就直接返回了
 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
  return beanInstance;
 }   

 Object object = null;
 if (mbd == null) {    
        // 如果 mbd 為空,則從緩存加載 bean(FactoryBean 生成的單例 bean 實(shí)例會(huì)緩存到 factoryBeanObjectCache 集合中,方便使用)
  object = getCachedObjectForFactoryBean(beanName);
 }   

 if (object == null) {
  // 到這,beanInstance 是 FactoryBean 類(lèi)型,所以就強(qiáng)轉(zhuǎn)了
  FactoryBean factory = (FactoryBean) beanInstance;
  // mbd 為空且判斷 containsBeanDefinition 是否包含 beanName
  if (mbd == null && containsBeanDefinition(beanName)) {    
            // 合并 BeanDefinition
   mbd = getMergedLocalBeanDefinition(beanName);
  }    
  boolean synthetic = (mbd != null && mbd.isSynthetic());   
        // 調(diào)用 getObjectFromFactoryBean 獲取實(shí)例 
  object = getObjectFromFactoryBean(factory, beanName, !synthetic);
 }
 return object;
}
 
  • (!(beanInstance instanceof FactoryBean),這里判斷就是這個(gè) bean 是不是 FactoryBean,不是就直接返回了
  • 如果 mbd 為空,則從緩存加載 bean(FactoryBean 生成的單例 bean 實(shí)例會(huì)緩存到 factoryBeanObjectCache 集合中,方便使用)
  • 調(diào)用 getObjectFromFactoryBean 獲取實(shí)例,這里會(huì)包括一部分對(duì)單例以及非單例的處理,以及最終返回 factory.getObject(); 對(duì)應(yīng)的 Bean 實(shí)例
 

四、測(cè)試案例

 

1. 別名






 
@Test
public void test_alias() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-alias.xml");
    UserService userService = beanFactory.getBean("userService-alias02", UserService.class);
    logger.info("獲取 Bean 通過(guò)別名:{}", userService);
}
 
Bean的獲取過(guò)程是什么  
  • 在單元測(cè)試 getBean 的時(shí)候,會(huì)看到它會(huì)把別名逐步處理掉,最終獲取到原有的 BeanName
 

2. 依賴(lài)



 
@Test
public void test_depends_on() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-depends-on.xml");
    UserService userService = beanFactory.getBean(UserService.class, "userService");
    logger.info("獲取 Bean:{}", userService.getUserDao());
}
 
Bean的獲取過(guò)程是什么  
  • 涉及到依賴(lài)會(huì)走到 dependsOn != null 下,獲取到依賴(lài)的 Bean 實(shí)例。
 

3. BeanFactory


 
@Test
public void test_factory_bean() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-bean.xml");
    UserDao userDao = beanFactory.getBean("userDao", UserDao.class);
    logger.info("獲取 Bean:{}", userDao);
}
 
Bean的獲取過(guò)程是什么  
  • 實(shí)現(xiàn) FactoryBean 的類(lèi)會(huì)需要實(shí)現(xiàn) getObject 方法,所有此類(lèi)的 Bean 最終都是獲取 getObject 

到此,相信大家對(duì)“Bean的獲取過(guò)程是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!


當(dāng)前名稱(chēng):Bean的獲取過(guò)程是什么
本文鏈接:http://weahome.cn/article/jocpei.html

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部