- 前言:在上文bean加載過程中還要一個非常重要的方法沒有分析createBean,該方法非常重要,是以特意提出來單獨分析。
createBean方法定義在AbstractBeanFactory中:

該方法根據給定的beanName、BeanDefinition和args執行個體化一個bean對象。所有bean執行個體的建立都會委托給該方法實作。
AbstractAutowireCapableBeanFactory#createBean
createBean的預設實作在AbstractAutowireCapableBeanFactory類中,代碼如下:
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 }
分析:
- 通過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中。
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進行處理。
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 }
根據方法名,從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的入口:
-
【spring源碼分析】IOC容器初始化(八)
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,下午。