日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
詳解Spring如何創(chuàng)建Bean對象?

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

目前成都創(chuàng)新互聯公司已為千余家的企業(yè)提供了網站建設、域名、虛擬空間、綿陽服務器托管、企業(yè)網站設計、揭西網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發(fā)展。

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

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

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

值得注意是的:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

創(chuàng)建 bean 對象是在 doCreateBean 方法中實現的,如下:

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

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

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

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

就是這樣。

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

小結

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

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

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

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


文章題目:詳解Spring如何創(chuàng)建Bean對象?
網頁鏈接:http://m.5511xx.com/article/cdcejoj.html