91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring 如何創建 Bean 對象

發布時間:2021-07-16 09:50:28 來源:億速云 閱讀:152 作者:chen 欄目:web開發

這篇文章主要講解了“Spring 如何創建 Bean 對象”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring 如何創建 Bean 對象”吧!

從整體上分析了如何從 Spring IoC 容器獲取一個 bean 對象。該邏輯由  AbstractBeanFactory#doGetBean 方法實現,主要流程如下:

Spring 如何創建 Bean 對象

本文進一步深入細節,主要分析如何創建 singleton(單例)類型的對象。

如何創建單例對象?

從流程圖可以看出,當獲取一個 bean 對象時,Spring 會首先嘗試從緩存中獲取單例對象。

值得注意是的:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 只有對象是單例的場景,即 scope 為 singleton 時才會緩存對象。

  3. 這里其實涉及到了所謂的「三級緩存」,為了更容易理解三級緩存,本文先研究這個 bean 對象是什么時候放入緩存的,后面再研究三級緩存。

既然能取,必然有地方把 bean 對象存入了緩存,那緩存中的數據是從哪里來的呢?

下面主要分析單例對象是如何創建、并放入緩存中的。

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

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {     // ...      protected <T> T doGetBean(             String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)             throws BeansException {          String beanName = transformedBeanName(name);         Object bean;          // 從緩存中獲取單例 bean 對象         Object sharedInstance = getSingleton(beanName);                  // 緩存中不存在 bean 對象         else {              // ...              try {                 // 獲取 BeanDefinition                 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);                  // 獲取依賴的 bean 對象                 // 若創建一個 bean 對象時依賴其他對象,則先創建被依賴對象                 // ...                  // 創建 scope 為 singleton(單例)的對象                 if (mbd.isSingleton()) {                     sharedInstance = getSingleton(beanName, () -> {                         try {                             return createBean(beanName, mbd, args);                         }                         catch (BeansException ex) {                             // ...                         }                     });                     // 處理 FactoryBean 的場景                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);                 }                  // 創建 scope 為 prototype 的對象                 else if (mbd.isPrototype()) {                     // ...                 }                  // 創建其他類型對象                 else {                     // ...                 }             }             catch (BeansException ex) {                 // ...             }         }          // 類型檢查          return (T) bean;     } }

其實就是這個 DefaultSingletonBeanRegistry#getSingleton 方法,代碼如下:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {     // 單例 bean 對象緩存(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 對象             Object singletonObject = this.singletonObjects.get(beanName);             // 緩存中不存在時再去創建             if (singletonObject == null) {                 // ...                 // 創建單例對象前                 beforeSingletonCreation(beanName);                 boolean newSingleton = false;                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);                 if (recordSuppressedExceptions) {                     this.suppressedExceptions = new LinkedHashSet<>();                 }                 try {                     // 創建單例對象                     singletonObject = singletonFactory.getObject();                     newSingleton = true;                 }                 // catch ...                 finally {                     if (recordSuppressedExceptions) {                         this.suppressedExceptions = null;                     }                     // 創建單例對象后                     afterSingletonCreation(beanName);                 }                 if (newSingleton) {                     // 將對象添加到緩存                     addSingleton(beanName, singletonObject);                 }             }             // 緩存中有的話直接返回             return singletonObject;         }     }  }

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

創建的邏輯在哪呢?

看代碼是通過 ObjectFactory#getObject 方法來創建的,ObjectFactory 是一個函數式接口:

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

這個方法的實現是什么呢?退回上一層,即 getBean 方法,看這里:

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

這里用到了 Lambda 表達式,將如下表達式作為參數:

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

創建 bean 對象的邏輯就在這個 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.             // 這里可能返回代理對象             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);             if (bean != null) {                 return bean;             }         }         // catch ...          try {             // 創建 bean 對象             Object beanInstance = doCreateBean(beanName, mbdToUse, args);             if (logger.isTraceEnabled()) {                 logger.trace("Finished creating instance of bean '" + beanName + "'");             }             return beanInstance;         }         // catch ...     } }
  • 值得注意的是,resolveBeforeInstantiation 方法其實是跟 AOP 實現相關的,可能在這里生成代理對象就返回了。由于現在主要分析  IoC 的流程,因此這里暫時略過,有興趣的朋友們可以自行研究。

這里繼續沿著主線邏輯走。

創建 bean 對象是在 doCreateBean 方法中實現的,如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory         implements AutowireCapableBeanFactory {      protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)             throws BeanCreationException {          // Instantiate the bean.         // 1. 實例化 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 雖然看起來有點像,但它倆不是一回事,前者是“實例化”,后者是“初始化”。

這個方法看起來有點長,但最主要的事情只有三件:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 創建 bean 對象:createBeanInstance 方法

  3. 填充屬性:populateBean 方法

  4. 初始化 bean:initializeBean 方法

這幾個方法內部其實都有一大堆堆堆堆堆&hellip;&hellip;的代碼,再對照一下前面給出的整體流程圖 :

Spring 如何創建 Bean 對象

就是這樣。

本文在前文整體分析的基礎上又進一步細化,先到這里吧,后面再繼續分析~

小結

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

本文在前文的基礎上又進一步細化,主要從整體上探討了 Spring 如何創建單例的 bean 對象,整體上分為三個步驟:

  1. 創建 bean 對象。

  2. 填充 bean 屬性

  3. 初始化 bean 對象

感謝各位的閱讀,以上就是“Spring 如何創建 Bean 對象”的內容了,經過本文的學習后,相信大家對Spring 如何創建 Bean 對象這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

甘南县| 偃师市| 潞西市| 北川| 东安县| 衡南县| 成安县| 富蕴县| 巢湖市| 易门县| 彰化市| 肇东市| 东明县| 新化县| 蒲江县| 南充市| 德保县| 罗定市| 崇阳县| 肇庆市| 柳江县| 清流县| 容城县| 新源县| 资源县| 张家港市| 高邑县| 墨脱县| 德昌县| 兴宁市| 新巴尔虎左旗| 通辽市| 布尔津县| 老河口市| 泊头市| 淳化县| 西乌珠穆沁旗| 彰化县| 海门市| 陆川县| 临夏市|