【spring源碼分析】IOC容器初始化(八)

  • 前言:在上文bean加載過程當中還要一個很是重要的方法沒有分析createBean,該方法很是重要,所以特地提出來單獨分析。

createBean方法定義在AbstractBeanFactory中:java

該方法根據給定的beanName、BeanDefinition和args實例化一個bean對象。全部bean實例的建立都會委託給該方法實現。緩存

AbstractAutowireCapableBeanFactory#createBean

createBean的默認實如今AbstractAutowireCapableBeanFactory類中,代碼以下:app

 1 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 2             throws BeanCreationException {
 3         if (logger.isDebugEnabled()) {
 4             logger.debug("Creating instance of bean '" + beanName + "'");
 5         }
 6         RootBeanDefinition mbdToUse = mbd;
 7 
 8         // Make sure bean class is actually resolved at this point, and
 9         // clone the bean definition in case of a dynamically resolved Class
10         // which cannot be stored in the shared merged bean definition.
11         // 確保此時的bean已經被解析了
12         // 若是獲取的class屬性不爲null,則克隆該BeanDefinition,主要是由於動態解析的class沒法保存到共享的BeanDefinition
13         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
14         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
15             mbdToUse = new RootBeanDefinition(mbd);
16             mbdToUse.setBeanClass(resolvedClass);
17         }
18 
19         // Prepare method overrides.
20         try {
21             // 驗證和準備覆蓋方法
22             mbdToUse.prepareMethodOverrides();
23         } catch (BeanDefinitionValidationException ex) {
24             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
25                                                    beanName, "Validation of method overrides failed", ex);
26         }
27 
28         try {
29             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
30             // 實例化的前置處理
31             // 給BeanPostProcessor一個機會用來返回一個代理類而不是真正的實例類
32             // AOP的功能就是基於這個地方
33             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
34             if (bean != null) {
35                 return bean;
36             }
37         } catch (Throwable ex) {
38             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
39                                             "BeanPostProcessor before instantiation of bean failed", ex);
40         }
41 
42         try {
43             // 建立Bean對象
44             Object beanInstance = doCreateBean(beanName, mbdToUse, args);
45             if (logger.isDebugEnabled()) {
46                 logger.debug("Finished creating instance of bean '" + beanName + "'");
47             }
48             return beanInstance;
49         } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
50             // A previously detected exception with proper bean creation context already,
51             // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
52             throw ex;
53         } catch (Throwable ex) {
54             throw new BeanCreationException(
55                     mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
56         }
57     }

分析:ide

  • 經過resolveBeanClass解析BeanDefinition的class屬性。
  • 處理override屬性。
  • 經過resolveBeforeInstantiation進行實例化的前置處理。
  • 最後經過doCreateBean建立bean對象。

AbstractBeanFactory#resolveBeanClass

 1 protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
 2             throws CannotLoadBeanClassException {
 3 
 4         try {
 5             if (mbd.hasBeanClass()) {
 6                 return mbd.getBeanClass();
 7             }
 8             if (System.getSecurityManager() != null) {
 9                 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
10                         doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
11             } else {
12                 return doResolveBeanClass(mbd, typesToMatch);
13             }
14         // ..... 省略異常處理
15     }

分析:函數

該方法主要是解析BeanDefinition的class類,若是解析的class類不爲空,則將其設置到mbdToUse中,由於動態解析的class沒法保存到共享的BeanDefinition中。post

AbstractBeanFactory#prepareMethodOverrides

 1 public void prepareMethodOverrides() throws BeanDefinitionValidationException {
 2         // Check that lookup methods exists.
 3         // 若是方法能夠覆蓋
 4         if (hasMethodOverrides()) {
 5             // 獲得覆蓋方法
 6             Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
 7             // 同步
 8             synchronized (overrides) {
 9                 // 循環調用 prepareMethodOverride進行覆蓋準備
10                 for (MethodOverride mo : overrides) {
11                     prepareMethodOverride(mo);
12                 }
13             }
14         }
15     }

分析:性能

bean標籤中的lookup-method和replace-method屬性就是放在BeanDefinition的methodOverrides屬性中(關於這兩個屬性的分析後續再來分析),這裏就是對methodOverrides屬性進行處理,動態爲當前bean生產代理並使用對應的攔截器爲bean作加強處理。優化

上述處理邏輯就是循環獲取MethodOverride屬性,而後調用prepareMethodOverride進行處理。this

 1 // AbstractBeanDefinition
 2 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
 3         int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
 4         if (count == 0) {
 5             throw new BeanDefinitionValidationException(
 6                     "Invalid method override: no method with name '" + mo.getMethodName() +
 7                             "' on class [" + getBeanClassName() + "]");
 8         } else if (count == 1) {
 9             // Mark override as not overloaded, to avoid the overhead of arg type checking.
10             mo.setOverloaded(false);
11         }
12     }

分析:spa

根據方法名,從class中獲取該方法名的個數:

  • 若是方法名個數爲0,則拋出BeanDefinitionValidationException異常,緣由其實很簡單:經過方法名去查找,而又沒有找到,則說明有問題,拋出異常。
  • 若是方法名個數爲1,則設置該方法未被重載(overloaded屬性模式爲true)。若是一個類存在多個重載方法,在方法調用的時候還需根據參數類型來判斷到底重載的是哪一個方法,這裏經過count=1,來表示該方法未被重載,在調用的時候能夠直接找方法而不須要進行方法參數的校驗,至關於一個小小的優化,提高後面調用函數的速度。

AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

 1 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
 2         Object bean = null;
 3         // 若是bean不是應用系統的,有BeanPostProcessor
 4         if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
 5             // Make sure bean class is actually resolved at this point.
 6             if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
 7                 Class<?> targetType = determineTargetType(beanName, mbd);
 8                 if (targetType != null) {
 9                     // 前置處理
10                     bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
11                     if (bean != null) {
12                         // 後置處理
13                         bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
14                     }
15                 }
16             }
17             mbd.beforeInstantiationResolved = (bean != null);
18         }
19         return bean;
20     }

分析:

經過applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization對bean實例化前進行前置與後置處理。若是返回了代理對象,則直接返回結果,Spring後續實現AOP就是基於這個地方進行的判斷。

前置處理與後置處理後續再具體進行分析。

AbstractAutowireCapableBeanFactory#doCreateBean

  1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  2             throws BeanCreationException {
  3 
  4         // Instantiate the bean.
  5         // BeanWrapper是對Bean的包裝,其接口中所定義的功能很簡單包括設置獲取被包裝的對象、獲取被包裝bean的屬性描述器
  6         BeanWrapper instanceWrapper = null;
  7         // 若是是單例模型,則從未完成的FactoryBean緩存中刪除
  8         if (mbd.isSingleton()) {
  9             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 10         }
 11         // 使用合適的實例化策略來建立新的實例:工廠方法、構造函數自動注入、簡單初始化
 12         if (instanceWrapper == null) {
 13             instanceWrapper = createBeanInstance(beanName, mbd, args);
 14         }
 15         // 包裝的對象實例
 16         final Object bean = instanceWrapper.getWrappedInstance();
 17         // 包裝的實例對象的類型
 18         Class<?> beanType = instanceWrapper.getWrappedClass();
 19         if (beanType != NullBean.class) {
 20             mbd.resolvedTargetType = beanType;
 21         }
 22 
 23         // Allow post-processors to modify the merged bean definition.
 24         // 先作同步,而後判斷是否有後置處理
 25         synchronized (mbd.postProcessingLock) {
 26             if (!mbd.postProcessed) {
 27                 try {
 28                     // 後置處理修改BeanDefinition
 29                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 30                 } catch (Throwable ex) {
 31                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 32                                                     "Post-processing of merged bean definition failed", ex);
 33                 }
 34                 mbd.postProcessed = true;
 35             }
 36         }
 37 
 38         // Eagerly cache singletons to be able to resolve circular references
 39         // even when triggered by lifecycle interfaces like BeanFactoryAware.
 40         // 解決單例模式的循環依賴         // 單例模式               運行循環依賴
 41         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 42                 isSingletonCurrentlyInCreation(beanName));// 當前單例bean是否正在被建立
 43         if (earlySingletonExposure) {
 44             if (logger.isDebugEnabled()) {
 45                 logger.debug("Eagerly caching bean '" + beanName +
 46                                      "' to allow for resolving potential circular references");
 47             }
 48             // 提早將建立的bean實例加入到singletonFactories中
 49             // 爲了後期避免循環依賴
 50             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 51         }
 52 
 53         // Initialize the bean instance.
 54         // 開始初始化bean實例對象
 55         Object exposedObject = bean;
 56         try {
 57             // 對bean進行填充,主要是進行屬性注入,其中,可能存在依賴於其餘bean的屬性,則會遞歸初始化依賴bean
 58             populateBean(beanName, mbd, instanceWrapper);
 59             // 進行bean初始化
 60             exposedObject = initializeBean(beanName, exposedObject, mbd);
 61         } catch (Throwable ex) {
 62             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 63                 throw (BeanCreationException) ex;
 64             } else {
 65                 throw new BeanCreationException(
 66                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 67             }
 68         }
 69 
 70         // 循環依賴處理
 71         if (earlySingletonExposure) {
 72             // 獲取earlySingletonReference
 73             Object earlySingletonReference = getSingleton(beanName, false);
 74             // 只有在循環依賴的狀況下,earlySingletonReference纔不會爲null
 75             if (earlySingletonReference != null) {
 76                 // 若是exposedObject沒有在初始化方法中改變,也就是沒有被加強
 77                 if (exposedObject == bean) {
 78                     exposedObject = earlySingletonReference;
 79                 } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 處理依賴
 80                     String[] dependentBeans = getDependentBeans(beanName);
 81                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
 82                     for (String dependentBean : dependentBeans) {
 83                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 84                             actualDependentBeans.add(dependentBean);
 85                         }
 86                     }
 87                     if (!actualDependentBeans.isEmpty()) {
 88                         throw new BeanCurrentlyInCreationException(beanName,
 89                                                                    "Bean with name '" + beanName + "' has been injected into other beans [" +
 90                                                                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 91                                                                            "] in its raw version as part of a circular reference, but has eventually been " +
 92                                                                            "wrapped. This means that said other beans do not use the final version of the " +
 93                                                                            "bean. This is often the result of over-eager type matching - consider using " +
 94                                                                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
 95                     }
 96                 }
 97             }
 98         }
 99 
100         // Register bean as disposable.
101         try {
102             // 註冊bean
103             registerDisposableBeanIfNecessary(beanName, bean, mbd);
104         } catch (BeanDefinitionValidationException ex) {
105             throw new BeanCreationException(
106                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
107         }
108 
109         return exposedObject;
110     }

分析:

若是沒有代理對象,則會進行bean對象的建立。

  • 若是BeanDefinition爲單例模式,首先從FactoryBean緩存中刪除該beanName的緩存。
  • 調用createBeanInstance方法建立一個BeanWrapper對象。
  • 調用applyMergedBeanDefinitionPostProcessors對BeanDefinition進行後置處理
  • 進行單例模式的循環依賴處理。
  • 調用populateBean進行bean屬性填充。
  • 調用initializeBean進行bean初始化。
  • 進行依賴檢查。
  • 最後註冊bean。

上述列出了建立bean對象的主要步驟,過程仍是比較複雜的,下面一一進行分析。主要關注點createBeanInstance、populateBean、initializeBean三個函數。

AbstractAutowireCapableBeanFactory#createBeanInstance

 1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
 2         // Make sure bean class is actually resolved at this point.
 3         // 解析bean,將bean類名解析爲class引用
 4         Class<?> beanClass = resolveBeanClass(mbd, beanName);
 5 
 6         if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
 7             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 8                                             "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
 9         }
10 
11         // 若是存在supplier回調,則使用給定的回調方法初始化策略
12         Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
13         if (instanceSupplier != null) {
14             return obtainFromSupplier(instanceSupplier, beanName);
15         }
16 
17         // 使用FactoryBean的factor-method來建立bean,支持靜態工廠和實例工廠
18         if (mbd.getFactoryMethodName() != null) {
19             return instantiateUsingFactoryMethod(beanName, mbd, args);
20         }
21 
22         // Shortcut when re-creating the same bean...
23         boolean resolved = false;
24         boolean autowireNecessary = false;
25         if (args == null) {
26             // 作同步
27             synchronized (mbd.constructorArgumentLock) {
28                 // 若是已緩存的解析構造函數或者工廠方法不爲null,則能夠利用構造函數解析
29                 // 由於須要根據參數確認到底使用哪一個構造函數,該過程比較消耗性能,因此採用緩存機制
30                 if (mbd.resolvedConstructorOrFactoryMethod != null) {
31                     resolved = true;
32                     autowireNecessary = mbd.constructorArgumentsResolved;
33                 }
34             }
35         }
36         // 已經解析好了,直接注入便可
37         if (resolved) {
38             // autowire自動注入,調用構造函數自動注入
39             if (autowireNecessary) {
40                 return autowireConstructor(beanName, mbd, null, null);
41             } else {
42                 // 使用默認構造函數構造
43                 return instantiateBean(beanName, mbd);
44             }
45         }
46 
47         // Need to determine the constructor...
48         // 肯定解析的構造函數
49         // 主要是檢查已經註冊的SmartInstantiationAwareBeanPostProcessor
50         Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
51         // 肯定構造方法進行bean建立
52         if (ctors != null ||
53                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
54                 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
55             return autowireConstructor(beanName, mbd, ctors, args);
56         }
57 
58         // 有參數,又沒有獲取到構造方法,則只能調用無參構造方法來建立實例
59         // 這是一個兜底的方法
60         // No special handling: simply use no-arg constructor.
61         return instantiateBean(beanName, mbd);
62     }

分析:

bean的實例化一個比較複雜的過程。

  • 若是設置Supplier回調,則調用obtainFromSupplier方法進行初始化。
  • 若是存在工廠方法,則使用工廠方法進行初始化。
  • 先判斷緩存中是否存在構造函數,若是存在,則根據是否使用自動注入,仍是默認的構造函數進行bean對象的初始化。
  • 若是緩存中不存在,則需先判斷到底使用哪一個構造函數來完成解析工做。
  • 若是上述條件仍是不知足,則使用無參構造方法來建立實例。

#1.若是設置Supplier回調,則使用obtainFromSupplier方法進行初始化。

首先了解下Supplier接口(java.util.function)

  • Supplier接口僅有一個功能性的get()方法,該方法會返回一個<T>類型的對象,有點相似工廠方法。
  • 若是咱們在建立BeanDefinition的時候設置了Supplier參數,那麼其餘的構造器或者工廠方法就沒有做用了。
  • AbstractBeanDefinition中提供了設置Supplier的入口:

AbstractAutowireCapableBeanFactory#obtainFromSupplier

 1 protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
 2         // 得到原建立的Bean的對象名
 3         String outerBean = this.currentlyCreatedBean.get();
 4         // 設置新的Bean對象名到currentlyCreatedBean中
 5         this.currentlyCreatedBean.set(beanName);
 6         Object instance;
 7         try {
 8             // 調用Supplier的get(),返回一個Bean對象
 9             instance = instanceSupplier.get();
10         } finally {
11             // 設置原建立的Bean對象名到currentlyCreatedBean中
12             if (outerBean != null) {
13                 this.currentlyCreatedBean.set(outerBean);
14             } else {
15                 this.currentlyCreatedBean.remove();
16             }
17         }
18         // 建立BeanWrapper對象
19         BeanWrapper bw = new BeanWrapperImpl(instance);
20         // 初始化BeanWrapper
21         initBeanWrapper(bw);
22         return bw;
23     }

分析:

  • 調用Supplier#get方法,獲取一個Bean實例對象。
  • 根據該實例對象構建BeanWrapper對象。
  • 最後初始化該對象。

若是存在工廠方法,則會調用工廠方法來完成bean的初始化工做,該方法實現比較長,而且細節複雜,因爲篇幅緣由放在下篇文章中解析。

總結

這裏僅僅分析了doCreateBean方法中的一點點內容,若是存在Supplier回調,則會直接經過Supplier來建立Bean對象,構造函數和工廠方法則失效,下面將對分析使用工廠方法實例化Bean對象的過程。


by Shawn Chen,2019.04.23,下午。

相關文章
相關標籤/搜索