成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解Spring 如何創建 Bean 對象?

開發 前端
本文在前文的基礎上又進一步細化,主要從整體上探討了 Spring 如何創建單例的 bean 對象。

[[385910]]

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


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

如何創建單例對象?

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

值得注意是的:

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

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

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

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

  1. public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { 
  2.     // ... 
  3.  
  4.     protected <T> T doGetBean( 
  5.             String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 
  6.             throws BeansException { 
  7.  
  8.         String beanName = transformedBeanName(name); 
  9.         Object bean; 
  10.  
  11.         // 從緩存中獲取單例 bean 對象 
  12.         Object sharedInstance = getSingleton(beanName); 
  13.          
  14.         // 緩存中不存在 bean 對象 
  15.         else { 
  16.  
  17.             // ... 
  18.  
  19.             try { 
  20.                 // 獲取 BeanDefinition 
  21.                 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 
  22.  
  23.                 // 獲取依賴的 bean 對象 
  24.                 // 若創建一個 bean 對象時依賴其他對象,則先創建被依賴對象 
  25.                 // ... 
  26.  
  27.                 // 創建 scope 為 singleton(單例)的對象 
  28.                 if (mbd.isSingleton()) { 
  29.                     sharedInstance = getSingleton(beanName, () -> { 
  30.                         try { 
  31.                             return createBean(beanName, mbd, args); 
  32.                         } 
  33.                         catch (BeansException ex) { 
  34.                             // ... 
  35.                         } 
  36.                     }); 
  37.                     // 處理 FactoryBean 的場景 
  38.                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 
  39.                 } 
  40.  
  41.                 // 創建 scope 為 prototype 的對象 
  42.                 else if (mbd.isPrototype()) { 
  43.                     // ... 
  44.                 } 
  45.  
  46.                 // 創建其他類型對象 
  47.                 else { 
  48.                     // ... 
  49.                 } 
  50.             } 
  51.             catch (BeansException ex) { 
  52.                 // ... 
  53.             } 
  54.         } 
  55.  
  56.         // 類型檢查 
  57.  
  58.         return (T) bean; 
  59.     } 

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

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 
  2.     // 單例 bean 對象緩存(beanName, bean) 
  3.     private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 
  4.  
  5.     public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { 
  6.         Assert.notNull(beanName, "Bean name must not be null"); 
  7.         synchronized (this.singletonObjects) { 
  8.             // 先從緩存中獲取 bean 對象 
  9.             Object singletonObject = this.singletonObjects.get(beanName); 
  10.             // 緩存中不存在時再去創建 
  11.             if (singletonObject == null) { 
  12.                 // ... 
  13.                 // 創建單例對象前 
  14.                 beforeSingletonCreation(beanName); 
  15.                 boolean newSingleton = false
  16.                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 
  17.                 if (recordSuppressedExceptions) { 
  18.                     this.suppressedExceptions = new LinkedHashSet<>(); 
  19.                 } 
  20.                 try { 
  21.                     // 創建單例對象 
  22.                     singletonObject = singletonFactory.getObject(); 
  23.                     newSingleton = true
  24.                 } 
  25.                 // catch ... 
  26.                 finally { 
  27.                     if (recordSuppressedExceptions) { 
  28.                         this.suppressedExceptions = null
  29.                     } 
  30.                     // 創建單例對象后 
  31.                     afterSingletonCreation(beanName); 
  32.                 } 
  33.                 if (newSingleton) { 
  34.                     // 將對象添加到緩存 
  35.                     addSingleton(beanName, singletonObject); 
  36.                 } 
  37.             } 
  38.             // 緩存中有的話直接返回 
  39.             return singletonObject; 
  40.         } 
  41.     } 
  42.  

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

創建的邏輯在哪呢?

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

  1. @FunctionalInterface 
  2. public interface ObjectFactory<T> { 
  3.     T getObject() throws BeansException; 

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

  1. sharedInstance = getSingleton(beanName, () -> { 
  2.     try { 
  3.         // 創建 bean 對象 
  4.         return createBean(beanName, mbd, args); 
  5.     } 
  6.     catch (BeansException ex) { 
  7.         // ... 
  8.     } 
  9. }); 

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

  1. () -> { 
  2.     try { 
  3.         // 創建 bean 對象 
  4.         return createBean(beanName, mbd, args); 
  5.     } 
  6.     catch (BeansException ex) { 
  7.         // ... 
  8.     } 

創建 bean 對象的邏輯就在這個 createBean 方法中,它在 AbstractAutowireCapableBeanFactory 類中:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory 
  2.         implements AutowireCapableBeanFactory { 
  3.  
  4.     @Override 
  5.     protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 
  6.             throws BeanCreationException { 
  7.  
  8.         RootBeanDefinition mbdToUse = mbd; 
  9.  
  10.         Class<?> resolvedClass = resolveBeanClass(mbd, beanName); 
  11.         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { 
  12.             mbdToUse = new RootBeanDefinition(mbd); 
  13.             mbdToUse.setBeanClass(resolvedClass); 
  14.         } 
  15.  
  16.         // Prepare method overrides. 
  17.         try { 
  18.             mbdToUse.prepareMethodOverrides(); 
  19.         } 
  20.         // catch ... 
  21.  
  22.         try { 
  23.             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 
  24.             // 這里可能返回代理對象 
  25.             Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 
  26.             if (bean != null) { 
  27.                 return bean; 
  28.             } 
  29.         } 
  30.         // catch ... 
  31.  
  32.         try { 
  33.             // 創建 bean 對象 
  34.             Object beanInstance = doCreateBean(beanName, mbdToUse, args); 
  35.             if (logger.isTraceEnabled()) { 
  36.                 logger.trace("Finished creating instance of bean '" + beanName + "'"); 
  37.             } 
  38.             return beanInstance; 
  39.         } 
  40.         // catch ... 
  41.     } 
  • 值得注意的是,resolveBeforeInstantiation 方法其實是跟 AOP 實現相關的,可能在這里生成代理對象就返回了。由于現在主要分析 IoC 的流程,因此這里暫時略過,有興趣的朋友們可以自行研究。

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

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

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory 
  2.         implements AutowireCapableBeanFactory { 
  3.  
  4.     protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 
  5.             throws BeanCreationException { 
  6.  
  7.         // Instantiate the bean. 
  8.         // 1. 實例化 bean 
  9.         BeanWrapper instanceWrapper = null
  10.         if (mbd.isSingleton()) { 
  11.             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 
  12.         } 
  13.         if (instanceWrapper == null) { 
  14.             instanceWrapper = createBeanInstance(beanName, mbd, args); 
  15.         } 
  16.         Object bean = instanceWrapper.getWrappedInstance(); 
  17.         Class<?> beanType = instanceWrapper.getWrappedClass(); 
  18.         if (beanType != NullBean.class) { 
  19.             mbd.resolvedTargetType = beanType; 
  20.         } 
  21.  
  22.         // Allow post-processors to modify the merged bean definition. 
  23.         synchronized (mbd.postProcessingLock) { 
  24.             if (!mbd.postProcessed) { 
  25.                 try { 
  26.                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 
  27.                 } 
  28.                 // catch ... 
  29.                 mbd.postProcessed = true
  30.             } 
  31.         } 
  32.  
  33.         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 
  34.                 isSingletonCurrentlyInCreation(beanName)); 
  35.         if (earlySingletonExposure) { 
  36.             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 
  37.         } 
  38.  
  39.         // Initialize the bean instance. 
  40.         Object exposedObject = bean; 
  41.         try { 
  42.             // 2. 填充屬性 
  43.             populateBean(beanName, mbd, instanceWrapper); 
  44.             // 3. 初始化 
  45.             exposedObject = initializeBean(beanName, exposedObject, mbd); 
  46.         } 
  47.         // catch ... 
  48.  
  49.         if (earlySingletonExposure) { 
  50.             Object earlySingletonReference = getSingleton(beanName, false); 
  51.             if (earlySingletonReference != null) { 
  52.                 if (exposedObject == bean) { 
  53.                     exposedObject = earlySingletonReference; 
  54.                 } 
  55.                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 
  56.                     String[] dependentBeans = getDependentBeans(beanName); 
  57.                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); 
  58.                     for (String dependentBean : dependentBeans) { 
  59.                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 
  60.                             actualDependentBeans.add(dependentBean); 
  61.                         } 
  62.                     } 
  63.                     // ... 
  64.                 } 
  65.             } 
  66.         } 
  67.  
  68.         // Register bean as disposable. 
  69.         try { 
  70.             registerDisposableBeanIfNecessary(beanName, bean, mbd); 
  71.         } 
  72.         // catch ... 
  73.  
  74.         return exposedObject; 
  75.     } 
  76.  
  • 注意:Instantiate 和 Initialize 雖然看起來有點像,但它倆不是一回事,前者是“實例化”,后者是“初始化”。

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

  1. 創建 bean 對象:createBeanInstance 方法
  2. 填充屬性:populateBean 方法
  3. 初始化 bean:initializeBean 方法

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

就是這樣。

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

小結

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

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

  1. 創建 bean 對象。
  2. 填充 bean 屬性
  3. 初始化 bean 對象

至于這三個步驟具體又做了什么,且聽下回分解。

 

責任編輯:姜華 來源: WriteOnRead
相關推薦

2011-03-18 09:27:00

Spring

2023-10-07 08:35:07

依賴注入Spring

2021-02-03 08:02:50

Spring Bean框架

2023-02-27 08:09:42

SpringAOP代理

2023-11-03 08:19:18

SpringBean容器

2011-04-12 09:53:32

Spring

2024-05-29 08:19:03

2020-12-11 08:04:22

SpringAOPBean

2021-12-08 11:18:21

Spring Bean面試題生命周期

2019-07-24 08:34:35

Java對象數據結構

2024-05-28 07:55:31

SpringBean用域

2022-05-27 08:25:55

容器Spring

2022-06-23 10:47:57

Spring容器工具

2021-05-11 07:42:59

BeanSpring屬性

2024-02-23 10:33:34

SpringBean容器

2011-08-01 09:50:46

iPhone 獲取對象 UIView

2009-06-17 17:20:14

BeanFactorySpring

2009-06-17 17:04:37

BeanFactorySpring

2023-09-28 08:15:05

SpringBean加載

2021-12-06 08:30:49

SpringSpring Bean面試題
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美国产亚洲一区二区 | 欧美一级在线 | 一级片免费视频 | 成人精品视频免费 | 久久在视频| 亚洲热在线视频 | 亚洲欧洲中文日韩 | 精品影视| 久久久精品国产 | 日韩在线视频网址 | 婷婷精品 | 亚洲国产精品日本 | 四虎影院久久 | 一区二区三区不卡视频 | 国产成人精品av | 成人在线视频免费观看 | 黄色精品| 精品乱子伦一区二区三区 | 97成人免费 | 日韩三级在线观看 | 久色激情 | 精品国产不卡一区二区三区 | 日本亚洲欧美 | 成人在线免费电影 | 涩涩视频在线播放 | 国产在线一区二区三区 | 亚洲视频 欧美视频 | 精品久久久久久国产 | 天天干视频 | 国户精品久久久久久久久久久不卡 | 精品久久久久久久久久久久久 | 免费一区二区三区在线视频 | 精品一区二区观看 | 超碰男人天堂 | 久草久草久草 | 亚洲一区免费 | 91在线中文字幕 | 欧美精品a∨在线观看不卡 欧美日韩中文字幕在线播放 | 中文字幕91av | 一级黄色片在线看 | 国产精品免费一区二区三区 |