IoC 之加載 Bean:總結


上文中我們將bean已經加載到了IOC容器中,接下來我們將把IOC加載Bean出來進行代碼解析 備注:(有些解釋是參考別個博客的相關解釋 )一起探討請加我QQ:1051980588

bean 的初始化節點,由第一次(顯式或者隱式)調用 #getBean(...) 方法來開啟,所以我們從這個方法開始。代碼如下:

 

  1 // AbstractBeanFactory.java
  2 
  3 public Object getBean(String name) throws BeansException {
  4     return doGetBean(name, null, null, false);
  5 }
  6 
  7 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  8         @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  9     // <1> 返回 bean 名稱,剝離工廠引用前綴。
 10     // 如果 name 是 alias ,則獲取對應映射的 beanName 。
 11     final String beanName = transformedBeanName(name);
 12     Object bean;
 13 
 14     // 從緩存中或者實例工廠中獲取 Bean 對象
 15     // Eagerly check singleton cache for manually registered singletons.
 16     Object sharedInstance = getSingleton(beanName);
 17     if (sharedInstance != null && args == null) {
 18         if (logger.isTraceEnabled()) {
 19             if (isSingletonCurrentlyInCreation(beanName)) {
 20                 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 21                         "' that is not fully initialized yet - a consequence of a circular reference");
 22             } else {
 23                 logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 24             }
 25         }
 26         // <2> 完成 FactoryBean 的相關處理,並用來獲取 FactoryBean 的處理結果
 27         bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 28     } else {
 29         // Fail if we're already creating this bean instance:
 30         // We're assumably within a circular reference.
 31         // <3> 因為 Spring 只解決單例模式下得循環依賴,在原型模式下如果存在循環依賴則會拋出異常。
 32         if (isPrototypeCurrentlyInCreation(beanName)) {
 33             throw new BeanCurrentlyInCreationException(beanName);
 34         }
 35 
 36         // <4> 如果容器中沒有找到,則從父類容器中加載
 37         // Check if bean definition exists in this factory.
 38         BeanFactory parentBeanFactory = getParentBeanFactory();
 39         if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 40             // Not found -> check parent.
 41             String nameToLookup = originalBeanName(name);
 42             if (parentBeanFactory instanceof AbstractBeanFactory) {
 43                 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 44                         nameToLookup, requiredType, args, typeCheckOnly);
 45             } else if (args != null) {
 46                 // Delegation to parent with explicit args.
 47                 return (T) parentBeanFactory.getBean(nameToLookup, args);
 48             } else if (requiredType != null) {
 49                 // No args -> delegate to standard getBean method.
 50                 return parentBeanFactory.getBean(nameToLookup, requiredType);
 51             } else {
 52                 return (T) parentBeanFactory.getBean(nameToLookup);
 53             }
 54         }
 55 
 56         // <5> 如果不是僅僅做類型檢查則是創建bean,這里需要記錄 
 57         if (!typeCheckOnly) {
 58             markBeanAsCreated(beanName);
 59         }
 60 
 61         try {
 62             // <6> 從容器中獲取 beanName 相應的 GenericBeanDefinition 對象,並將其轉換為 RootBeanDefinition 對象
 63             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 64             // 檢查給定的合並的 BeanDefinition
 65             checkMergedBeanDefinition(mbd, beanName, args);
 66 
 67             // Guarantee initialization of beans that the current bean depends on.
 68             // <7> 處理所依賴的 bean
 69             String[] dependsOn = mbd.getDependsOn();
 70             if (dependsOn != null) {
 71                 for (String dep : dependsOn) {
 72                     // 若給定的依賴 bean 已經注冊為依賴給定的 bean
 73                     // 循環依賴的情況
 74                     if (isDependent(beanName, dep)) {
 75                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 76                                 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 77                     }
 78                     // 緩存依賴調用 TODO 芋艿
 79                     registerDependentBean(dep, beanName);
 80                     try {
 81                         getBean(dep);
 82                     } catch (NoSuchBeanDefinitionException ex) {
 83                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 84                                 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 85                     }
 86                 }
 87             }
 88 
 89             // <8> bean 實例化
 90             // Create bean instance.
 91             if (mbd.isSingleton()) { // 單例模式
 92                 sharedInstance = getSingleton(beanName, () -> {
 93                     try {
 94                         return createBean(beanName, mbd, args);
 95                     }
 96                     catch (BeansException ex) {
 97                         // Explicitly remove instance from singleton cache: It might have been put there
 98                         // eagerly by the creation process, to allow for circular reference resolution.
 99                         // Also remove any beans that received a temporary reference to the bean.
100                         // 顯式從單例緩存中刪除 Bean 實例
101                         // 因為單例模式下為了解決循環依賴,可能他已經存在了,所以銷毀它。 TODO 芋艿
102                         destroySingleton(beanName);
103                         throw ex;
104                     }
105                 });
106                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
107             } else if (mbd.isPrototype()) { // 原型模式
108                 // It's a prototype -> create a new instance.
109                 Object prototypeInstance;
110                 try {
111                     beforePrototypeCreation(beanName);
112                     prototypeInstance = createBean(beanName, mbd, args);
113                 } finally {
114                     afterPrototypeCreation(beanName);
115                 }
116                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
117             } else {
118                 // 從指定的 scope 下創建 bean
119                 String scopeName = mbd.getScope();
120                 final Scope scope = this.scopes.get(scopeName);
121                 if (scope == null) {
122                     throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
123                 }try {
124                     Object scopedInstance = scope.get(beanName, () -> {
125                         beforePrototypeCreation(beanName);
126                         try {
127                             return createBean(beanName, mbd, args);
128                         } finally {
129                             afterPrototypeCreation(beanName);
130                         }
131                     });
132                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
133                 } catch (IllegalStateException ex) {
134                     throw new BeanCreationException(beanName,
135                             "Scope '" + scopeName + "' is not active for the current thread; consider " +
136                             "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
137                             ex);
138                 }
139             }
140         } catch (BeansException ex) {
141             cleanupAfterBeanCreationFailure(beanName);
142             throw ex;
143         }
144     }
145 
146     // <9> 檢查需要的類型是否符合 bean 的實際類型
147     // Check if required type matches the type of the actual bean instance.
148     if (requiredType != null && !requiredType.isInstance(bean)) {
149         try {
150             T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
151             if (convertedBean == null) {
152                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
153             }
154             return convertedBean;
155         } catch (TypeMismatchException ex) {
156             if (logger.isTraceEnabled()) {
157                 logger.trace("Failed to convert bean '" + name + "' to required type '" +
158                         ClassUtils.getQualifiedName(requiredType) + "'", ex);
159             }
160             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
161         }
162     }
163     return (T) bean;
164 }

內部調用 #doGetBean(...) 方法。#doGetBean(...) 方法的代碼量比較多,從這里就可以看出 bean 的加載過程是一個非常復雜的過程,會涉及到各種各樣的情況處理。

#doGetBean(...) 方法,可以分為以下幾個過程:

  1. 轉換 beanName 。因為我們調用 #getBean(...) 方法傳入的 name 並不一定就是 beanName,可以傳入 aliasName,FactoryBean,所以這里需要進行簡單的轉換過程。
  2. 嘗試從緩存中加載單例 bean 。
  3. bean 的實例化。
  4. 原型模式的依賴檢查。因為 Spring 只會解決單例模式的循環依賴,對於原型模式的循環依賴都是直接拋出 BeanCurrentlyInCreationException 異常。
  5. 嘗試從 parentBeanFactory 獲取 bean 實例。如果 parentBeanFactory != null && !containsBeanDefinition(beanName) 則嘗試從 parentBeanFactory 中獲取 bean 實例對象,因為 !containsBeanDefinition(beanName) 就意味着定義的 xml 文件中沒有 beanName 相應的配置,這個時候就只能從 parentBeanFactory 中獲取。
  6. 獲取 RootBeanDefinition,並對其進行合並檢查。從緩存中獲取已經解析的 RootBeanDefinition 。同時,如果父類不為 null的話,則會合並父類的屬性。
  7. 依賴檢查。某個 bean 依賴其他 bean ,則需要先加載依賴的 bean。
  8. 對不同的 scope 進行處理。
  9. 類型轉換處理。如果傳遞的 requiredType 不為 null,則需要檢測所得到 bean 的類型是否與該 requiredType 一致。如果不一致則嘗試轉換,當然也要能夠轉換成功,否則拋出 BeanNotOfRequiredTypeException 異常。

下面就以下幾個方面進行闡述,說明 Spring bean 的加載過程。

  1. 從緩存中獲取 bean
  2. 創建 bean 實例對象
  3. 從 bean 實例中獲取對象

1. 從緩存中獲取 bean

Spring 中根據 scope 可以將 bean 分為以下幾類:singleton、prototype 和 其他,這樣分的原因在於 Spring 在對不同 scope 處理的時候是這么處理的:

  • singleton :在 Spring 的 IoC 容器中只存在一個對象實例,所有該對象的引用都共享這個實例。Spring 容器只會創建該 bean 定義的唯一實例,這個實例會被保存到緩存中,並且對該bean的所有后續請求和引用都將返回該緩存中的對象實例。
  • prototype :每次對該bean的請求都會創建一個新的實例
  • 其他 :
    • request:每次 http 請求將會有各自的 bean 實例。
    • session:在一個 http session 中,一個 bean 定義對應一個 bean 實例。
    • global session:在一個全局的 http session 中,一個 bean 定義對應一個 bean 實例。

所以,從緩存中獲取的 bean 一定是 singleton bean,這也是 Spring 為何只解決 singleton bean 的循環依賴。調用 #getSingleton(String beanName) 方法,從緩存中獲取 singleton bean。代碼如下:

 

 1 // DefaultSingletonBeanRegistry.java
 2 
 3 public Object getSingleton(String beanName) {
 4     return getSingleton(beanName, true);
 5 }
 6 
 7 @Nullable
 8 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 9     // 從單例緩沖中加載 bean
10     Object singletonObject = this.singletonObjects.get(beanName);
11     // 緩存中的 bean 為空,且當前 bean 正在創建
12     if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
13         // 加鎖
14         synchronized (this.singletonObjects) {
15             // 從 earlySingletonObjects 獲取
16             singletonObject = this.earlySingletonObjects.get(beanName);
17             // earlySingletonObjects 中沒有,且允許提前創建
18             if (singletonObject == null && allowEarlyReference) {
19                 // 從 singletonFactories 中獲取對應的 ObjectFactory
20                 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
21                 if (singletonFactory != null) {
22                     // 獲得 bean
23                     singletonObject = singletonFactory.getObject();
24                     // 添加 bean 到 earlySingletonObjects 中
25                     this.earlySingletonObjects.put(beanName, singletonObject);
26                     // 從 singletonFactories 中移除對應的 ObjectFactory
27                     this.singletonFactories.remove(beanName);
28                 }
29             }
30         }
31     }
32     return singletonObject;
33 }

 

該方法就是從 singletonObjectsearlySingletonObjects、 singletonFactories 三個緩存中獲取,這里也是 Spring 解決 bean 循環依賴的關鍵之處。

2. 創建 bean 實例對象

如果緩存中沒有,也沒有 parentBeanFactory ,則會調用 #createBean(String beanName, RootBeanDefinition mbd, Object[] args) 方法,創建 bean 實例。該方法主要是在處理不同 scope 的 bean 的時候進行調用。代碼如下:

1 // AbstractBeanFactory.java
2 
3 protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
4             throws BeanCreationException;

 

  • 該方法是定義在 AbstractBeanFactory 中的抽象方法,其含義是根據給定的 BeanDefinition 和 args 實例化一個 bean 對象。如果該 BeanDefinition 存在父類,則該 BeanDefinition 已經合並了父類的屬性。所有 Bean 實例的創建都會委托給該方法實現。
  • 方法接受三個參數:
    • beanName :bean 的名字。
    • mbd :已經合並了父類屬性的(如果有的話)BeanDefinition 。
    • args :用於構造函數或者工廠方法創建 bean 實例對象的參數 。

該抽象方法的默認實現是在類 AbstractAutowireCapableBeanFactory 中實現,該方法其實只是做一些檢查和驗證工作,真正的初始化工作是由 #doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法來實現。代碼如下

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


#doCreateBean(...) 方法,是創建 bean 實例的核心方法,它的整體思路是:

  • <1> 處,如果是單例模式,則清除 factoryBeanInstanceCache 緩存,同時返回 BeanWrapper 實例對象,當然如果存在。
  • <2> 處,如果緩存中沒有 BeanWrapper 或者不是單例模式,則調用 #createBeanInstance(...) 方法,實例化 bean,主要是將 BeanDefinition 轉換為 BeanWrapper 。
  • <3> 處,MergedBeanDefinitionPostProcessor 的應用。
  • <4> 處,單例模式的循環依賴處理。
  • <5> 處,調用 #populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) 方法,進行屬性填充。將所有屬性填充至 bean 的實例中。
  • <6> 處,調用 #initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法,初始化 bean 。
  • <7> 處,依賴檢查。
  • <8> 處,注冊 DisposableBean 。

2.1 實例化 bean

如果緩存中沒有 BeanWrapper 實例對象或者該 bean 不是 singleton,則調用 #createBeanInstance(...) 方法。創建 bean 實例。該方法主要是根據參數 BeanDefinition、args[] 來調用構造函數實例化 bean 對象。過程較為復雜,代碼如下:

 1 // AbstractAutowireCapableBeanFactory.java
 2 
 3 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
 4     // Make sure bean class is actually resolved at this point.
 5     // 解析 bean ,將 bean 類名解析為 class 引用。
 6     Class<?> beanClass = resolveBeanClass(mbd, beanName); 7 8 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { // 校驗 9 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 10 "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); 11  } 12 13 // <1> 如果存在 Supplier 回調,則使用給定的回調方法初始化策略 14 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); 15 if (instanceSupplier != null) { 16 return obtainFromSupplier(instanceSupplier, beanName); 17  } 18 19 // <2> 使用 FactoryBean 的 factory-method 來創建,支持靜態工廠和實例工廠 20 if (mbd.getFactoryMethodName() != null) { 21 return instantiateUsingFactoryMethod(beanName, mbd, args); 22  } 23 24 // <3> Shortcut when re-creating the same bean... 25 boolean resolved = false; 26 boolean autowireNecessary = false; 27 if (args == null) { 28 // constructorArgumentLock 構造函數的常用鎖 29 synchronized (mbd.constructorArgumentLock) { 30 // 如果已緩存的解析的構造函數或者工廠方法不為空,則可以利用構造函數解析 31 // 因為需要根據參數確認到底使用哪個構造函數,該過程比較消耗性能,所有采用緩存機制 32 if (mbd.resolvedConstructorOrFactoryMethod != null) { 33 resolved = true; 34 autowireNecessary = mbd.constructorArgumentsResolved; 35  } 36  } 37  } 38 // 已經解析好了,直接注入即可 39 if (resolved) { 40 // <3.1> autowire 自動注入,調用構造函數自動注入 41 if (autowireNecessary) { 42 return autowireConstructor(beanName, mbd, null, null); 43 } else { 44 // <3.2> 使用默認構造函數構造 45 return instantiateBean(beanName, mbd); 46  } 47  } 48 49 // Candidate constructors for autowiring? 50 // <4> 確定解析的構造函數 51 // 主要是檢查已經注冊的 SmartInstantiationAwareBeanPostProcessor 52 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 53 // <4.1> 有參數情況時,創建 Bean 。先利用參數個數,類型等,確定最精確匹配的構造方法。 54 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || 55 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 56 return autowireConstructor(beanName, mbd, ctors, args); 57  } 58 59 // Preferred constructors for default construction? 60 // <4.1> 選擇構造方法,創建 Bean 。 61 ctors = mbd.getPreferredConstructors(); 62 if (ctors != null) { 63 return autowireConstructor(beanName, mbd, ctors, null); // args = null 64  } 65 66 // No special handling: simply use no-arg constructor. 67 // <4.2> 有參數時,又沒獲取到構造方法,則只能調用無參構造方法來創建實例了(兜底方法) 68 return instantiateBean(beanName, mbd); 69 }

實例化 Bean 對象,是一個復雜的過程,其主要的邏輯為:

  • <1> 處,如果存在 Supplier 回調,則調用 #obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) 方法,進行初始化。
  • <2> 處,如果存在工廠方法,則使用工廠方法進行初始化。
  • <3> 處,首先判斷緩存,如果緩存中存在,即已經解析過了,則直接使用已經解析了的。根據 constructorArgumentsResolved 參數來判斷:
    • <3.1> 處,是使用構造函數自動注入,即調用 #autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) 方法。
    • <3.2> 處,還是默認構造函數,即調用 #instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。
  • <4> 處,如果緩存中沒有,則需要先確定到底使用哪個構造函數來完成解析工作,因為一個類有多個構造函數,每個構造函數都有不同的構造參數,所以需要根據參數來鎖定構造函數並完成初始化。
    • <4.1> 處,如果存在參數,則使用相應的帶有參數的構造函數,即調用 #autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) 方法。
    • <4.2> 處,否則,使用默認構造函數,即調用 #instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。

其實核心思想還是在於根據不同的情況執行不同的實例化策略,主要是包括如下四種策略:

  1. Supplier 回調
  2. #instantiateUsingFactoryMethod(...) 方法,工廠方法初始化
  3. #autowireConstructor(...) 方法,構造函數自動注入初始化
  4. #instantiateBean(...) 方法,默認構造函數注入

其實無論哪種策略,他們的實現邏輯都差不多:確定構造函數和構造方法,然后實例化。只不過相對於 Supplier 回調和默認構造函數注入而言,工廠方法初始化和構造函數自動注入初始化會比較復雜,因為他們構造函數和構造參數的不確定性,Spring 需要花大量的精力來確定構造函數和構造參數,如果確定了則好辦,直接選擇實例化策略即可。當然在實例化的時候會根據是否有需要覆蓋或者動態替換掉的方法,因為存在覆蓋或者織入的話需要創建動態代理將方法織入,這個時候就只能選擇 CGLIB 的方式來實例化,否則直接利用反射的方式即可。

2.2 屬性填充

屬性填充其實就是將 BeanDefinition 的屬性值賦值給 BeanWrapper 實例對象的過程。在填充的過程需要根據注入的類型不同來區分是根據類型注入還是名字注入,當然在這個過程還會涉及循環依賴的問題的。代碼如下:

  1 // AbstractAutowireCapableBeanFactory.java
  2 
  3 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  4     // 沒有實例化對象
  5     if (bw == null) {
  6         // 有屬性,則拋出 BeanCreationException 異常
  7         if (mbd.hasPropertyValues()) {
  8             throw new BeanCreationException(
  9                     mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
 10             // 沒有屬性,直接 return 返回
 11         } else {
 12             // Skip property population phase for null instance.
 13             return;
 14         }
 15     }
 16 
 17     // <1> 在設置屬性之前給 InstantiationAwareBeanPostProcessors 最后一次改變 bean 的機會
 18     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
 19     // state of the bean before properties are set. This can be used, for example,
 20     // to support styles of field injection.
 21     boolean continueWithPropertyPopulation = true;
 22     if (!mbd.isSynthetic()  // bean 不是"合成"的,即未由應用程序本身定義
 23             && hasInstantiationAwareBeanPostProcessors()) { // 是否持有 InstantiationAwareBeanPostProcessor
 24         // 迭代所有的 BeanPostProcessors
 25         for (BeanPostProcessor bp : getBeanPostProcessors()) {
 26             if (bp instanceof InstantiationAwareBeanPostProcessor) { // 如果為 InstantiationAwareBeanPostProcessor
 27                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
 28                 // 返回值為是否繼續填充 bean
 29                 // postProcessAfterInstantiation:如果應該在 bean上面設置屬性則返回 true,否則返回 false
 30                 // 一般情況下,應該是返回true 。
 31                 // 返回 false 的話,將會阻止在此 Bean 實例上調用任何后續的 InstantiationAwareBeanPostProcessor 實例。
 32                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
 33                     continueWithPropertyPopulation = false;
 34                     break;
 35                 }
 36             }
 37         }
 38     }
 39     // 如果后續處理器發出停止填充命令,則終止后續操作
 40     if (!continueWithPropertyPopulation) {
 41         return;
 42     }
 43 
 44     // bean 的屬性值
 45     PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
 46 
 47     // <2> 自動注入
 48     if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 49         // 將 PropertyValues 封裝成 MutablePropertyValues 對象
 50         // MutablePropertyValues 允許對屬性進行簡單的操作,並提供構造函數以支持Map的深度復制和構造。
 51         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
 52         // Add property values based on autowire by name if applicable.
 53         // 根據名稱自動注入
 54         if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
 55             autowireByName(beanName, mbd, bw, newPvs);
 56         }
 57         // Add property values based on autowire by type if applicable.
 58         // 根據類型自動注入
 59         if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 60             autowireByType(beanName, mbd, bw, newPvs);
 61         }
 62         pvs = newPvs;
 63     }
 64 
 65     // 是否已經注冊了 InstantiationAwareBeanPostProcessors
 66     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
 67     // 是否需要進行【依賴檢查】
 68     boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
 69 
 70     // <3> BeanPostProcessor 處理
 71     PropertyDescriptor[] filteredPds = null;
 72     if (hasInstAwareBpps) {
 73         if (pvs == null) {
 74             pvs = mbd.getPropertyValues();
 75         }
 76         // 遍歷 BeanPostProcessor 數組
 77         for (BeanPostProcessor bp : getBeanPostProcessors()) {
 78             if (bp instanceof InstantiationAwareBeanPostProcessor) {
 79                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
 80                 // 對所有需要依賴檢查的屬性進行后處理
 81                 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
 82                 if (pvsToUse == null) {
 83                     // 從 bw 對象中提取 PropertyDescriptor 結果集
 84                     // PropertyDescriptor:可以通過一對存取方法提取一個屬性
 85                     if (filteredPds == null) {
 86                         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
 87                     }
 88                     pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
 89                     if (pvsToUse == null) {
 90                         return;
 91                     }
 92                 }
 93                 pvs = pvsToUse;
 94             }
 95         }
 96     }
 97     
 98     // <4> 依賴檢查
 99     if (needsDepCheck) {
100         if (filteredPds == null) {
101             filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
102         }
103         // 依賴檢查,對應 depends-on 屬性
104         checkDependencies(beanName, mbd, filteredPds, pvs);
105     }
106 
107     // <5> 將屬性應用到 bean 中
108     if (pvs != null) {
109         applyPropertyValues(beanName, mbd, bw, pvs);
110     }
111 }

 

處理流程如下:

  • <1> ,根據 hasInstantiationAwareBeanPostProcessors 屬性來判斷,是否需要在注入屬性之前給 InstantiationAwareBeanPostProcessors 最后一次改變 bean 的機會。此過程可以控制 Spring 是否繼續進行屬性填充。
  • 統一存入到 PropertyValues 中,PropertyValues 用於描述 bean 的屬性。
    • <2> ,根據注入類型( AbstractBeanDefinition#getResolvedAutowireMode() 方法的返回值 )的不同來判斷:
      • 是根據名稱來自動注入(#autowireByName(...)
      • 還是根據類型來自動注入(#autowireByType(...)
    • <3> ,進行 BeanPostProcessor 處理。
    • <4> ,依賴檢測。
  • <5> ,將所有 PropertyValues 中的屬性,填充到 BeanWrapper 中。

2.3 初始化 bean

初始化 bean 為 #createBean(...) 方法的最后一個過程,代碼如下:

 1 // AbstractAutowireCapableBeanFactory.java
 2 
 3 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 4     if (System.getSecurityManager() != null) { // 安全模式
 5         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 6             // <1> 激活 Aware 方法,對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAware
 7             invokeAwareMethods(beanName, bean);
 8             return null;
 9         }, getAccessControlContext());
10     } else {
11         // <1> 激活 Aware 方法,對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAware
12         invokeAwareMethods(beanName, bean);
13     }
14 
15     // <2> 后處理器,before
16     Object wrappedBean = bean;
17     if (mbd == null || !mbd.isSynthetic()) {
18         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
19     }
20 
21     // <3> 激活用戶自定義的 init 方法
22     try {
23         invokeInitMethods(beanName, wrappedBean, mbd);
24     } catch (Throwable ex) {
25         throw new BeanCreationException(
26                 (mbd != null ? mbd.getResourceDescription() : null),
27                 beanName, "Invocation of init method failed", ex);
28     }
29 
30     // <2> 后處理器,after
31     if (mbd == null || !mbd.isSynthetic()) {
32         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
33     }
34 
35     return wrappedBean;
36 }

初始化 bean 的方法其實就是三個步驟的處理,而這三個步驟主要還是根據用戶設定的來進行初始化,這三個過程為:

  • <1> 激活 Aware 方法。
  • <3> 后置處理器的應用。
  • <2> 激活自定義的 init 方法。

3. 從 bean 實例中獲取對象

無論是從單例緩存中獲取的 bean 實例 還是通過 #createBean(...) 方法來創建的 bean 實例,最終都會調用 #getObjectForBeanInstance(...) 方法來根據傳入的 bean 實例獲取對象,按照 Spring 的傳統,該方法也只是做一些檢測工作,真正的實現邏輯是委托給 #getObjectFromFactoryBean(...) 方法來實現。代碼如下:

 1 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
 2     // <1> 為單例模式且緩存中存在
 3     if (factory.isSingleton() && containsSingleton(beanName)) {
 4         synchronized (getSingletonMutex()) { // <1.1> 單例鎖
 5             // <1.2> 從緩存中獲取指定的 factoryBean
 6             Object object = this.factoryBeanObjectCache.get(beanName);
 7             if (object == null) {
 8                 // 為空,則從 FactoryBean 中獲取對象
 9                 object = doGetObjectFromFactoryBean(factory, beanName);
10                 // 從緩存中獲取
11                 // TODO 芋艿,具體原因
12                 // Only post-process and store if not put there already during getObject() call above
13                 // (e.g. because of circular reference processing triggered by custom getBean calls)
14                 Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
15                 if (alreadyThere != null) {
16                     object = alreadyThere;
17                 } else {
18                     // <1.3> 需要后續處理
19                     if (shouldPostProcess) {
20                         // 若該 Bean 處於創建中,則返回非處理對象,而不是存儲它
21                         if (isSingletonCurrentlyInCreation(beanName)) {
22                             // Temporarily return non-post-processed object, not storing it yet..
23                             return object;
24                         }
25                         // 單例 Bean 的前置處理
26                         beforeSingletonCreation(beanName);
27                         try {
28                             // 對從 FactoryBean 獲取的對象進行后處理
29                             // 生成的對象將暴露給 bean 引用
30                             object = postProcessObjectFromFactoryBean(object, beanName);
31                         } catch (Throwable ex) {
32                             throw new BeanCreationException(beanName,
33                                     "Post-processing of FactoryBean's singleton object failed", ex);
34                         } finally {
35                             // 單例 Bean 的后置處理
36                             afterSingletonCreation(beanName);
37                         }
38                     }
39                     // <1.4> 添加到 factoryBeanObjectCache 中,進行緩存
40                     if (containsSingleton(beanName)) {
41                         this.factoryBeanObjectCache.put(beanName, object);
42                     }
43                 }
44             }
45             return object;
46         }
47     // <2>
48     } else {
49         // 為空,則從 FactoryBean 中獲取對象
50         Object object = doGetObjectFromFactoryBean(factory, beanName);
51         // 需要后續處理
52         if (shouldPostProcess) {
53             try {
54                 // 對從 FactoryBean 獲取的對象進行后處理
55                 // 生成的對象將暴露給 bean 引用
56                 object = postProcessObjectFromFactoryBean(object, beanName);
57             }
58             catch (Throwable ex) {
59                 throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
60             }
61         }
62         return object;
63     }
64 }

 

主要流程如下:

  • 若為單例且單例 Bean 緩存中存在 beanName ,則 <1> 進行后續處理(跳轉到下一步),否則,則 <2> 從 FactoryBean 中獲取 Bean 實例對象。
  • <1.1> 首先,獲取鎖。其實我們在前面篇幅中發現了大量的同步鎖,鎖住的對象都是 this.singletonObjects,主要是因為在單例模式中必須要保證全局唯一。
  • <1.2> 然后,從 factoryBeanObjectCache 緩存中獲取實例對象 object 。若 object 為空,則調用 #doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) 方法,從 FactoryBean 獲取對象,其實內部就是調用 FactoryBean#getObject() 方法。
  • <1.3> 如果需要后續處理( shouldPostProcess = true ),則進行進一步處理,步驟如下:
    • 若該 Bean 處於創建中(#isSingletonCurrentlyInCreation(String beanName) 方法返回 true ),則返回非處理的 Bean 對象,而不是存儲它。
    • 調用 #beforeSingletonCreation(String beanName) 方法,進行創建之前的處理。默認實現將該 Bean 標志為當前創建的。
    • 調用 #postProcessObjectFromFactoryBean(Object object, String beanName) 方法,對從 FactoryBean 獲取的 Bean 實例對象進行后置處理。
    • 調用 #afterSingletonCreation(String beanName) 方法,進行創建 Bean 之后的處理,默認實現是將該 bean 標記為不再在創建中。
  • <1.4> 最后,加入到 factoryBeanObjectCache 緩存中。

4. 小結

Spring 加載 bean 的整體過程都已經分析完畢了 深入分析了解 請加qq:1051980588 我們一起來探索


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM