<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring 如何創(chuàng)建 bean 對(duì)象?

          共 24304字,需瀏覽 49分鐘

           ·

          2021-06-08 10:32

          前情回顧

          前文「Spring 如何從 IoC 容器中獲取對(duì)象?」從整體上分析了如何從 Spring IoC 容器獲取一個(gè) bean 對(duì)象。該邏輯由 AbstractBeanFactory#doGetBean 方法實(shí)現(xiàn),主要流程如下:

          本文進(jìn)一步深入細(xì)節(jié),主要分析如何創(chuàng)建 singleton(單例)類(lèi)型的對(duì)象。

          如何創(chuàng)建單例對(duì)象?

          從流程圖可以看出,當(dāng)獲取一個(gè) bean 對(duì)象時(shí),Spring 會(huì)首先嘗試從緩存中獲取單例對(duì)象。

          值得注意是的:

          1. 只有對(duì)象是單例的場(chǎng)景,即 scope 為 singleton 時(shí)才會(huì)緩存對(duì)象。
          2. 這里其實(shí)涉及到了所謂的「三級(jí)緩存」,為了更容易理解三級(jí)緩存,本文先研究這個(gè) bean 對(duì)象是什么時(shí)候放入緩存的,后面再研究三級(jí)緩存。

          既然能取,必然有地方把 bean 對(duì)象存入了緩存,那緩存中的數(shù)據(jù)是從哪里來(lái)的呢?

          下面主要分析單例對(duì)象是如何創(chuàng)建、并放入緩存中的。

          該邏輯在 AbstractBeanFactory#doGetBean 方法中,主要代碼如下(保留了創(chuàng)建單例 bean 對(duì)象的代碼,其他部分暫時(shí)忽略):

          public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
              // ...

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

                      throws BeansException 
          {

                  String beanName = transformedBeanName(name);
                  Object bean;

                  // 從緩存中獲取單例 bean 對(duì)象
                  Object sharedInstance = getSingleton(beanName);
                  
                  // 緩存中不存在 bean 對(duì)象
                  else {

                      // ...

                      try {
                          // 獲取 BeanDefinition
                          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

                          // 獲取依賴(lài)的 bean 對(duì)象
                          // 若創(chuàng)建一個(gè) bean 對(duì)象時(shí)依賴(lài)其他對(duì)象,則先創(chuàng)建被依賴(lài)對(duì)象
                          // ...

                          // 創(chuàng)建 scope 為 singleton(單例)的對(duì)象
                          if (mbd.isSingleton()) {
                              sharedInstance = getSingleton(beanName, () -> {
                                  try {
                                      return createBean(beanName, mbd, args);
                                  }
                                  catch (BeansException ex) {
                                      // ...
                                  }
                              });
                              // 處理 FactoryBean 的場(chǎng)景
                              bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                          }

                          // 創(chuàng)建 scope 為 prototype 的對(duì)象
                          else if (mbd.isPrototype()) {
                              // ...
                          }

                          // 創(chuàng)建其他類(lèi)型對(duì)象
                          else {
                              // ...
                          }
                      }
                      catch (BeansException ex) {
                          // ...
                      }
                  }

                  // 類(lèi)型檢查

                  return (T) bean;
              }
          }

          其實(shí)就是這個(gè) DefaultSingletonBeanRegistry#getSingleton 方法,代碼如下:

          public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
              // 單例 bean 對(duì)象緩存(beanName, bean)
              private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

              public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
                  Assert.notNull(beanName, "Bean name must not be null");
                  synchronized (this.singletonObjects) {
                      // 先從緩存中獲取 bean 對(duì)象
                      Object singletonObject = this.singletonObjects.get(beanName);
                      // 緩存中不存在時(shí)再去創(chuàng)建
                      if (singletonObject == null) {
                          // ...
                          // 創(chuàng)建單例對(duì)象前
                          beforeSingletonCreation(beanName);
                          boolean newSingleton = false;
                          boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                          if (recordSuppressedExceptions) {
                              this.suppressedExceptions = new LinkedHashSet<>();
                          }
                          try {
                              // 創(chuàng)建單例對(duì)象
                              singletonObject = singletonFactory.getObject();
                              newSingleton = true;
                          }
                          // catch ...
                          finally {
                              if (recordSuppressedExceptions) {
                                  this.suppressedExceptions = null;
                              }
                              // 創(chuàng)建單例對(duì)象后
                              afterSingletonCreation(beanName);
                          }
                          if (newSingleton) {
                              // 將對(duì)象添加到緩存
                              addSingleton(beanName, singletonObject);
                          }
                      }
                      // 緩存中有的話(huà)直接返回
                      return singletonObject;
                  }
              }

          }

          getSingleton 方法會(huì)先從緩存 singletonObjects(其實(shí)就是一個(gè) Map)中獲取 bean 對(duì)象,如果緩存有就直接返回,否則再去創(chuàng)建。創(chuàng)建成功后,會(huì)把該對(duì)象存入緩存。

          創(chuàng)建的邏輯在哪呢?

          看代碼是通過(guò) ObjectFactory#getObject 方法來(lái)創(chuàng)建的,ObjectFactory 是一個(gè)函數(shù)式接口:

          @FunctionalInterface
          public interface ObjectFactory<T{
              getObject() throws BeansException;
          }

          這個(gè)方法的實(shí)現(xiàn)是什么呢?退回上一層,即 getBean 方法,看這里:

          sharedInstance = getSingleton(beanName, () -> {
              try {
                  // 創(chuàng)建 bean 對(duì)象
                  return createBean(beanName, mbd, args);
              }
              catch (BeansException ex) {
                  // ...
              }
          });

          這里用到了 Lambda 表達(dá)式,將如下表達(dá)式作為參數(shù):

          () -> {
              try {
                  // 創(chuàng)建 bean 對(duì)象
                  return createBean(beanName, mbd, args);
              }
              catch (BeansException ex) {
                  // ...
              }
          }

          創(chuàng)建 bean 對(duì)象的邏輯就在這個(gè) createBean 方法中,它在 AbstractAutowireCapableBeanFactory 類(lèi)中:

          public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
                  implements AutowireCapableBeanFactory 
          {

              @Override
              protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                      throws BeanCreationException 
          {

                  RootBeanDefinition mbdToUse = mbd;

                  Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
                  if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                      mbdToUse = new RootBeanDefinition(mbd);
                      mbdToUse.setBeanClass(resolvedClass);
                  }

                  // Prepare method overrides.
                  try {
                      mbdToUse.prepareMethodOverrides();
                  }
                  // catch ...

                  try {
                      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                      // 這里可能返回代理對(duì)象
                      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                      if (bean != null) {
                          return bean;
                      }
                  }
                  // catch ...

                  try {
                      // 創(chuàng)建 bean 對(duì)象
                      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                      if (logger.isTraceEnabled()) {
                          logger.trace("Finished creating instance of bean '" + beanName + "'");
                      }
                      return beanInstance;
                  }
                  // catch ...
              }
          }

          值得注意的是,resolveBeforeInstantiation 方法其實(shí)是跟 AOP 實(shí)現(xiàn)相關(guān)的,可能在這里生成代理對(duì)象就返回了。由于現(xiàn)在主要分析 IoC 的流程,因此這里暫時(shí)略過(guò),有興趣的朋友們可以自行研究。

          這里繼續(xù)沿著主線(xiàn)邏輯走。

          創(chuàng)建 bean 對(duì)象是在 doCreateBean 方法中實(shí)現(xiàn)的,如下:

          public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
                  implements AutowireCapableBeanFactory 
          {

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

                  // Instantiate the bean.
                  // 1. 實(shí)例化 bean
                  BeanWrapper instanceWrapper = null;
                  if (mbd.isSingleton()) {
                      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
                  }
                  if (instanceWrapper == null) {
                      instanceWrapper = createBeanInstance(beanName, mbd, args);
                  }
                  Object bean = instanceWrapper.getWrappedInstance();
                  Class<?> beanType = instanceWrapper.getWrappedClass();
                  if (beanType != NullBean.class{
                      mbd.resolvedTargetType = beanType;
                  }

                  // Allow post-processors to modify the merged bean definition.
                  synchronized (mbd.postProcessingLock) {
                      if (!mbd.postProcessed) {
                          try {
                              applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                          }
                          // catch ...
                          mbd.postProcessed = true;
                      }
                  }

                  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                          isSingletonCurrentlyInCreation(beanName));
                  if (earlySingletonExposure) {
                      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
                  }

                  // Initialize the bean instance.
                  Object exposedObject = bean;
                  try {
                      // 2. 填充屬性
                      populateBean(beanName, mbd, instanceWrapper);
                      // 3. 初始化
                      exposedObject = initializeBean(beanName, exposedObject, mbd);
                  }
                  // catch ...

                  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);
                                  }
                              }
                              // ...
                          }
                      }
                  }

                  // Register bean as disposable.
                  try {
                      registerDisposableBeanIfNecessary(beanName, bean, mbd);
                  }
                  // catch ...

                  return exposedObject;
              }

          }

          注意:Instantiate 和 Initialize 雖然看起來(lái)有點(diǎn)像,但它倆不是一回事,前者是“實(shí)例化”,后者是“初始化”。

          這個(gè)方法看起來(lái)有點(diǎn)長(zhǎng),但最主要的事情只有三件:

          1. 創(chuàng)建 bean 對(duì)象:createBeanInstance 方法
          2. 填充屬性:populateBean 方法
          3. 初始化 bean:initializeBean 方法

          這幾個(gè)方法內(nèi)部其實(shí)都有一大堆堆堆堆堆……的代碼,再對(duì)照一下前面給出的整體流程圖:

          就是這樣。

          本文在前文整體分析的基礎(chǔ)上又進(jìn)一步細(xì)化,先到這里吧,后面再繼續(xù)分析~

          小結(jié)

          如何從 Spring IoC 容器中獲取 bean 對(duì)象?前文對(duì)此進(jìn)行了整體流程的分析。

          本文在前文的基礎(chǔ)上又進(jìn)一步細(xì)化,主要從整體上探討了 Spring 如何創(chuàng)建單例的 bean 對(duì)象,整體上分為三個(gè)步驟:

          1. 創(chuàng)建 bean 對(duì)象
          2. 填充 bean 屬性
          3. 初始化 bean 對(duì)象

          至于這三個(gè)步驟具體又做了什么,且聽(tīng)下回分解。

          — 【 THE END 】—
          本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲取!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) PDF 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話(huà),在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 70
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩成人片。 | 黄级网站特一免费观看 | 大香蕉网在线视频 | 操熟女视频 | 国产在线视频你懂的 |