<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ì)象?

          共 24133字,需瀏覽 49分鐘

           ·

          2021-03-10 08:57

          前情回顧

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

          本文進(jìn)一步深入細(xì)節(jié),主要分析如何創(chuàng)建 singleton(單例)類型的對(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);

                          // 獲取依賴的 bean 對(duì)象
                          // 若創(chuàng)建一個(gè) bean 對(duì)象時(shí)依賴其他對(duì)象,則先創(chuàng)建被依賴對(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)建其他類型對(duì)象
                          else {
                              // ...
                          }
                      }
                      catch (BeansException ex) {
                          // ...
                      }
                  }

                  // 類型檢查

                  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);
                          }
                      }
                      // 緩存中有的話直接返回
                      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 類中:

          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ù)沿著主線邏輯走。

          創(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è)步驟具體又做了什么,且聽下回分解。

          有點(diǎn)「自頂向下」的感覺了,這就是「金字塔原理」?


          瀏覽 63
          點(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>
                  日韩免费高清视频 | 网站无遮挡内射 | 日本在残a视频观看视频 | 欧美激情视频网站 | 青青草在线观看免费视频 |