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

前言:在【spring源碼分析】IOC容器初始化(六)中分析了從單例緩存中加載bean對象,因爲篇幅緣由其核心函數html

FactoryBeanRegistrySupport#getObjectFromFactoryBean並未進行詳細分析,本文將繼續對bean加載過程的分析。spring


FactoryBeanRegistrySupport#getObjectFromFactoryBean

 1 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
 2         // 爲單例模式,其緩存中存在該bean實例
 3         if (factory.isSingleton() && containsSingleton(beanName)) {
 4             /**
 5              * 作同步,內部其實使用的就是{@link DefaultSingletonBeanRegistry#singletonObjects}
 6              */
 7             synchronized (getSingletonMutex()) {
 8                 // 從緩存中獲取指定的factoryBean
 9                 Object object = this.factoryBeanObjectCache.get(beanName);
10                 if (object == null) {
11                     // 爲空,則從FactoryBean中獲取對象
12                     object = doGetObjectFromFactoryBean(factory, beanName);
13                     // Only post-process and store if not put there already during getObject() call above
14                     // (e.g. because of circular reference processing triggered by custom getBean calls)
15                     // 再次從緩存中獲取bean對象,主要是由於循環依賴
16                     Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
17                     if (alreadyThere != null) {
18                         object = alreadyThere;
19                     } else {
20                         // 須要後續處理
21                         if (shouldPostProcess) {
22                             // 若是該Bean處於建立中,則返回處理對象,而不是存儲該對象
23                             if (isSingletonCurrentlyInCreation(beanName)) {
24                                 // Temporarily return non-post-processed object, not storing it yet..
25                                 return object;
26                             }
27                             // 單例bean的前置處理 用於添加標誌,當前bean正處於建立中
28                             beforeSingletonCreation(beanName);
29                             try {
30                                 // 對FactoryBean獲取的對象進行後置處理,返回生成的對象
31                                 object = postProcessObjectFromFactoryBean(object, beanName);
32                             } catch (Throwable ex) {
33                                 throw new BeanCreationException(beanName,
34                                                                 "Post-processing of FactoryBean's singleton object failed", ex);
35                             } finally {
36                                 // 單例bean的後置處理 和前置處理相反,前置添加,後置移除 移除標誌,當前bean不處於建立中
37                                 afterSingletonCreation(beanName);
38                             }
39                         }
40                         // 添加到factoryBeanObjectCache中進行緩存
41                         if (containsSingleton(beanName)) {
42                             this.factoryBeanObjectCache.put(beanName, object);
43                         }
44                     }
45                 }
46                 return object;
47             }
48         } else {
49             // 不知足第一個條件,不是單例,或者緩存中不存在,則從FactoryBean中獲取對象
50             Object object = doGetObjectFromFactoryBean(factory, beanName);
51             // 須要後續處理
52             if (shouldPostProcess) {
53                 try {
54                     // 對FactoryBean獲取的對象進行後處理
55                     // 返回生成的對象
56                     object = postProcessObjectFromFactoryBean(object, beanName);
57                 } catch (Throwable ex) {
58                     throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
59                 }
60             }
61             return object;
62         }
63     }

分析:緩存

函數分兩大分支:app

#1.單例且singletonObjects緩存中存在(該分支爲同步方法)ide

  • #1.1:FactoryBean爲單例,而且緩存中存在該bean對象(containsSingleton方法其實就是判斷singletonObjects集合中是否存在bean對象),首先從緩存中獲取factoryBean對象object,若是object=null,則從doGetObjectFromFactoryBean方法中獲取對象。注意:這裏再次從factoryBeanObjectCache緩存中嘗試獲取對象(主要是循環依賴問題,有可能這時該bean對象已經加載了,就不用再次加載了),若是緩存中已存在bean對象,則使用緩存中對象,並直接返回。
  • #1.2:若是factoryBeanObjectCache緩存中不存在對象且須要後置處理,則首先判斷該bean對象是否正在被建立,若是是,則直接返回,注意這裏未進行緩存;而後對單例bean進行前置添加處理(beforeSingletonCreation)、後置處理(postProcessObjectFromFactoryBean)、後置移除標誌處理(afterSingletonCreation)。
  • #1.3:最後將緩存生成的bean對象

#2.不知足(#1)中的任何一條件
函數

  • 首先從doGetObjectFromFactoryBean方法中獲取獲取bean對象,若是須要後置處理,則調用postProcessObjectFromFactoryBean方法進行處理,最後返回生成過的bean對象。

在上述分析中涉及到幾個函數,下面一一進行分析。源碼分析

FactoryBeanRegistrySupport#doGetObjectFromFactoryBean

 1 private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
 2             throws BeanCreationException {
 3 
 4         Object object;
 5         try {
 6             // 若是權限不爲空
 7             if (System.getSecurityManager() != null) {
 8                 AccessControlContext acc = getAccessControlContext();
 9                 try {
10                     // 從FactoryBean中獲取Bean對象[factory::getObject] 其實與else分支同樣的
11                     object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
12                 } catch (PrivilegedActionException pae) {
13                     throw pae.getException();
14                 }
15             } else {
16                 // 若是權限爲空,則從Factory中獲取Bean對象
17                 object = factory.getObject();
18             }
19         } catch (FactoryBeanNotInitializedException ex) {
20             throw new BeanCurrentlyInCreationException(beanName, ex.toString());
21         } catch (Throwable ex) {
22             throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
23         }
24 
25         // 進行一波校驗
26         // Do not accept a null value for a FactoryBean that's not fully
27         // initialized yet: Many FactoryBeans just return null then.
28         if (object == null) {
29             // 若是bean正在被建立,則拋出異常
30             if (isSingletonCurrentlyInCreation(beanName)) {
31                 throw new BeanCurrentlyInCreationException(
32                         beanName, "FactoryBean which is currently in creation returned null from getObject");
33             }
34             object = new NullBean();
35         }
36         return object;
37     }

分析:post

根據是否具備權限,經過FactoryBean#getObject獲取bean對象,若是bean對象爲null且正在被建立,則拋出異常,不然實例化一個NullBean對象進行返回。ui

DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation

 1     /**
 2      * 正在建立中的單例 Bean 的名字的集合
 3      * Names of beans that are currently in creation.
 4      */
 5     private final Set<String> singletonsCurrentlyInCreation =
 6             Collections.newSetFromMap(new ConcurrentHashMap<>(16));
 7 
 8 public boolean isSingletonCurrentlyInCreation(String beanName) {
 9         return this.singletonsCurrentlyInCreation.contains(beanName);
10     }

分析:this

該函數判斷bean是否正處於建立之中,該方法要與beforeSingletonCreation和afterSingletonCreation配合起來分析才能明白其重要性,他們記錄了bean的加載狀態,是檢查當前bean是否處於建立中的關鍵處,對解決bean的循環依賴起着重要做用。

DefaultSingletonBeanRegistry#beforeSingletonCreation

1     protected void beforeSingletonCreation(String beanName) {
2         // 這裏會添加到正在建立bean的集合中
3         // 注意第一個條件,若是存在,則爲false,直接短路
4         // 只有當第一個條件不存在[false]時,纔會去進行添加操做
5         if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
6             throw new BeanCurrentlyInCreationException(beanName);
7         }
8     }

分析:

注意這裏就會將正在建立的beanName添加到singletonsCurrentlyInCreation集合中,第一個條件是判斷該bean是否不會被檢測。

DefaultSingletonBeanRegistry#afterSingletonCreation

1 protected void afterSingletonCreation(String beanName) {
2         if (!this.inCreationCheckExclusions.contains(beanName)
3                 && !this.singletonsCurrentlyInCreation.remove(beanName)) { // 移除
4             // 若是移除失敗,則拋出IllegalStateException異常
5             throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
6         }
7     }

分析:

afterSingletonCreation方法與beforeSingletonCreation方法的功能相反,用於將beanName移除正在建立的集合singletonsCurrentlyInCreation,代表bean建立完成。

postProcessObjectFromFactoryBean

該方法的默認實現,就是返回當前bean對象。

1 // FactoryBeanRegistrySupport
2 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
3         return object;
4     }

固然,子類能夠對該方法進行重寫。

 1 // AbstractAutowireCapableBeanFactory
 2 
 3     protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
 4         return applyBeanPostProcessorsAfterInitialization(object, beanName);
 5     }
 6 
 7 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
 8             throws BeansException {
 9 
10         Object result = existingBean;
11         // 遍歷BeanPostProcessor
12         for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
13             // 進行處理
14             // TODO: 2019/4/2 具體處理過程需詳細查看,這裏先走大流程
15             Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
16             // 返回爲空,則返回傳入的Object對象
17             if (current == null) {
18                 return result;
19             }
20             // 修改result
21             result = current;
22         }
23         return result;
24     }

分析:

這裏主要是遍歷BeanPostProcessor,而後對bean對象進行處理,關於後置處理器的分析後面再作分析。

到這裏從單例緩存中獲取bean對象的相應源碼已分析完成,接下來看單例緩存中無bean對象時,Spring的處理流程,再次將getBean的切入點代碼貼出來。

  1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  2                               @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  3 
  4         // .........省略從單例緩存中獲取bean對象的代碼
  5         } else {
  6             // Fail if we're already creating this bean instance:
  7             // We're assumably within a circular reference.
  8             // Spring只能解決單例模式下的循環依賴,在原型模式下若是存在循環依賴則拋出異常
  9             // 這裏檢測原型模式下,該bean是否在加載,若是在加載則拋出異常
 10             if (isPrototypeCurrentlyInCreation(beanName)) {
 11                 throw new BeanCurrentlyInCreationException(beanName);
 12             }
 13 
 14             // 若是當前容器中沒有找到,則從父類容器中加載
 15             // Check if bean definition exists in this factory.
 16             BeanFactory parentBeanFactory = getParentBeanFactory();
 17             /**
 18              * 調用{@link DefaultListableBeanFactory#containsBeanDefinition(String)}方法
 19              * 其實就是在beanDefinitionMap中判斷是否存在beanName對應的BeanDefinition
 20              */
 21             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 22                 // Not found -> check parent.
 23                 // 肯定原始的beanName
 24                 String nameToLookup = originalBeanName(name);
 25                 // 若是父類容器爲AbstractBeanFactory,則委託父類處理
 26                 if (parentBeanFactory instanceof AbstractBeanFactory) {
 27                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 28                             nameToLookup, requiredType, args, typeCheckOnly);
 29                 } else if (args != null) { // 用明確的args從parentBeanFactory中,獲取Bean對象
 30                     // Delegation to parent with explicit args.
 31                     // 委託給父類構造函數getBean()處理
 32                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 33                 } else if (requiredType != null) { // 用明確的requiredType從parentBeanFactory中,獲取Bean對象
 34                     // No args -> delegate to standard getBean method.
 35                     // 沒有args,委託給標準的getBean()處理
 36                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 37                 } else {
 38                     // 直接使用nameToLookup從parentBeanFactory中獲取Bean對象
 39                     return (T) parentBeanFactory.getBean(nameToLookup);
 40                 }
 41             }
 42 
 43             // 若是不只僅是作類型檢查,而是建立bean,這裏須要記錄
 44             if (!typeCheckOnly) {
 45                 markBeanAsCreated(beanName);
 46             }
 47 
 48             try {
 49                 /**
 50                  * 從容器中獲取beanName對應的GenericBeanDefinition對象,並轉換成RootBeanDefinition對象
 51                  * GenericBeanDefinition的建立{@link BeanDefinitionReaderUtils#createBeanDefinition}方法
 52                  */
 53                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 54                 // 檢查合併的BeanDefinition
 55                 checkMergedBeanDefinition(mbd, beanName, args);
 56 
 57                 // Guarantee initialization of beans that the current bean depends on.
 58                 // 處理所依賴的bean
 59                 String[] dependsOn = mbd.getDependsOn();
 60                 if (dependsOn != null) {
 61                     for (String dep : dependsOn) {
 62                         // 若給定的依賴bean已經註冊爲依賴給定的bean
 63                         // 即循環依賴狀況,拋出BeanCreationException異常
 64                         if (isDependent(beanName, dep)) {
 65                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 66                                                             "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 67                         }
 68                         // 緩存依賴調用
 69                         registerDependentBean(dep, beanName);
 70                         try {
 71                             // 遞歸處理依賴 Bean
 72                             getBean(dep);
 73                         } catch (NoSuchBeanDefinitionException ex) {
 74                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 75                                                             "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 76                         }
 77                     }
 78                 }
 79                 // bean實例化
 80                 // Create bean instance.
 81                 // 單例模式
 82                 /**
 83                  * 這裏有個已建立bean的重要方法createBean
 84                  * {@link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])}
 85                  */
 86                 if (mbd.isSingleton()) {
 87                     sharedInstance = getSingleton(beanName, () -> {
 88                         try {
 89                             return createBean(beanName, mbd, args);
 90                         } catch (BeansException ex) {
 91                             // Explicitly remove instance from singleton cache: It might have been put there
 92                             // eagerly by the creation process, to allow for circular reference resolution.
 93                             // Also remove any beans that received a temporary reference to the bean.
 94                             // 顯式從單例緩存中刪除Bean實例
 95                             // 由於單例模式下爲了解決循環依賴,可能它已經存在,因此銷燬它
 96                             destroySingleton(beanName);
 97                             throw ex;
 98                         }
 99                     });
100                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
101                 } else if (mbd.isPrototype()) { // 原型模式
102                     // It's a prototype -> create a new instance.
103                     Object prototypeInstance = null;
104                     try {
105                         // 前置處理
106                         beforePrototypeCreation(beanName);
107                         /**
108                          * 建立bean {@link AbstractAutowireCapableBeanFactory#createBean}
109                          */
110                         prototypeInstance = createBean(beanName, mbd, args);
111                     } finally {
112                         /**
113                          * 後置處理 與前置處理相反從{@link prototypesCurrentlyInCreation}中移除
114                          */
115                         afterPrototypeCreation(beanName);
116                     }
117                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
118                 } else { //其餘做用域
119                     // 得到scopeName對應的Scope對象
120                     String scopeName = mbd.getScope();
121                     final Scope scope = this.scopes.get(scopeName);
122                     if (scope == null) {
123                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
124                     }
125                     try {
126                         /**
127                          * 從指定的scope下建立bean
128                          * {@link SimpleThreadScope#get方法}
129                          */
130                         Object scopedInstance = scope.get(beanName, () -> {
131                             beforePrototypeCreation(beanName);
132                             try {
133                                 return createBean(beanName, mbd, args);
134                             } finally {
135                                 afterPrototypeCreation(beanName);
136                             }
137                         });
138                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
139                     } catch (IllegalStateException ex) {
140                         throw new BeanCreationException(beanName,
141                                                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
142                                                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
143                                                         ex);
144                     }
145                 }
146             } catch (BeansException ex) {
147                 cleanupAfterBeanCreationFailure(beanName);
148                 throw ex;
149             }
150         }
151 
152         // 檢查須要的類型是否符合bean的實際類型
153         // Check if required type matches the type of the actual bean instance.
154         if (requiredType != null && !requiredType.isInstance(bean)) {
155             try {
156                 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
157                 if (convertedBean == null) {
158                     throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
159                 }
160                 return convertedBean;
161             } catch (TypeMismatchException ex) {
162                 if (logger.isTraceEnabled()) {
163                     logger.trace("Failed to convert bean '" + name + "' to required type '" +
164                                          ClassUtils.getQualifiedName(requiredType) + "'", ex);
165                 }
166                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
167             }
168         }
169         return (T) bean;
170     }

分析:

#1.首先經過AbstractBeanFactory#isPrototypeCurrentlyInCreation檢查bean對象是否處於原型模式下的循環依賴,由於Spring只能解決單例模式下的循環依賴,若是在原型模式下也存在該bean對象,則會拋出異常。

 1 // AbstractBeanFactory
 2     /**
 3      * 原型模式下存儲beanName的ThreadLocal<br/>
 4      * Names of beans that are currently in creation.
 5      */
 6     private final ThreadLocal<Object> prototypesCurrentlyInCreation =
 7             new NamedThreadLocal<>("Prototype beans currently in creation");
 8     protected boolean isPrototypeCurrentlyInCreation(String beanName) {
 9         Object curVal = this.prototypesCurrentlyInCreation.get();
10         return (curVal != null &&
11                 (curVal.equals(beanName) //相等
12                         || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
13     }
  • 這裏就是檢查原型模式的ThreadLocal中是否已經存在對應的beanName。

#2.AbstractBeanFactory#getParentBeanFactory檢查其父類BeanFactory是否存在,若是存在且beanDefinitionMap中不存在該BeanDefinition,則委託其父類經過getBean方法獲取bean對象。注意這裏首先會經過originalBeanName方法獲取原始beanName。

1 // AbstractBeanFactory
2     protected String originalBeanName(String name) {
3         String beanName = transformedBeanName(name);
4         if (name.startsWith(FACTORY_BEAN_PREFIX)) {
5             // 若是beanName以&開頭,則在加上&進行返回 由於transformedBeanName中會去掉&
6             beanName = FACTORY_BEAN_PREFIX + beanName;
7         }
8         return beanName;
9     }
  • 首先經過transformedBeanName(該方法前面已經分析)獲取真正的beanName,若是name以"&"開頭,則將beanName加上"&"符號,由於transformedBeanName方法會去掉"&"符號。

#3.判斷bean是否須要作類型檢查,若是不只僅作類型檢查,則須要調用markBeanAsCreated函數進行記錄。

 1 // AbstractBeanFactory
 2     /**
 3      * 已建立Bean的名字集合<br/>
 4      * Names of beans that have already been created at least once.
 5      */
 6     private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
 7 
 8 
 9 protected void markBeanAsCreated(String beanName) {
10         // 沒有建立
11         if (!this.alreadyCreated.contains(beanName)) {
12             // 作同步
13             synchronized (this.mergedBeanDefinitions) {
14                 // 再次進行檢查,DoubleCheck模式
15                 if (!this.alreadyCreated.contains(beanName)) {
16                     // Let the bean definition get re-merged now that we're actually creating
17                     // the bean... just in case some of its metadata changed in the meantime.
18                     // 從mergedBeanDefinitions中刪除beanName,並在下次訪問時從新建立它
19                     clearMergedBeanDefinition(beanName);
20                     // 添加到已建立bean集合中
21                     this.alreadyCreated.add(beanName);
22                 }
23             }
24         }
25     }

#4. 接下來將對BeanDefinition進行轉換,由於最開始建立的BeanDefinition類型爲GenericBeanDefinition,getMergedLocalBeanDefinition方法在前面已經進行了分析,這裏不在贅述。

#5.調用checkMergedBeanDefinition對轉換後的RootBeanDefinition,若是RootBeanDefinition仍爲抽象的,則拋出異常,這裏抽象的對象還不能進行實例化。代碼以下:

1 // AbstractBeanFactory
2 protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
3             throws BeanDefinitionStoreException {
4 
5         if (mbd.isAbstract()) {
6             throw new BeanIsAbstractException(beanName);
7         }
8     }

#6.處理依賴,若是在加載bean對象時,發現它有依賴bean的話,那麼在初始化該bean的時候須要先初始化依賴的bean對象

 1 // 處理所依賴的bean
 2                 String[] dependsOn = mbd.getDependsOn();
 3                 if (dependsOn != null) {
 4                     for (String dep : dependsOn) {
 5                         // 若給定的依賴bean已經註冊爲依賴給定的bean
 6                         // 即循環依賴狀況,拋出BeanCreationException異常
 7                         if (isDependent(beanName, dep)) {
 8                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 9                                                             "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
10                         }
11                         // 緩存依賴調用
12                         registerDependentBean(dep, beanName);
13                         try {
14                             // 遞歸處理依賴 Bean
15                             getBean(dep);
16                         } catch (NoSuchBeanDefinitionException ex) {
17                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
18                                                             "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
19                         }
20                     }
21                 }

分析:

DefaultSingletonBeanRegistry#isDependent

 1 protected boolean isDependent(String beanName, String dependentBeanName) {
 2         synchronized (this.dependentBeanMap) {
 3             return isDependent(beanName, dependentBeanName, null);
 4         }
 5     }
 6 private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
 7         // alreadySeen 已經檢測的依賴bean
 8         if (alreadySeen != null && alreadySeen.contains(beanName)) {
 9             return false;
10         }
11         // 獲取原始的beanName
12         String canonicalName = canonicalName(beanName);
13         // 獲取當前beanName的依賴集合
14         Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
15         // 不存在,則說明不存在註冊依賴
16         if (dependentBeans == null) {
17             return false;
18         }
19         // 存在,則證實已經存在註冊依賴
20         if (dependentBeans.contains(dependentBeanName)) {
21             return true;
22         }
23         // 遞歸檢測依賴
24         for (String transitiveDependency : dependentBeans) {
25             if (alreadySeen == null) {
26                 alreadySeen = new HashSet<>();
27             }
28             // 添加到alreadySeen
29             alreadySeen.add(beanName);
30             // 遞推
31             if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
32                 return true;
33             }
34         }
35         return false;
36     }

分析:

這裏經過一些列判斷,是否依賴的bean是否已經注入,若是注入則返回true,不然返回false。

#7.若是依賴檢測經過,則調用registerDependentBean對依賴bean進行注入。

 1 // DefaultSingletonBeanRegistry
 2 
 3     /**
 4      * 保存的是依賴beanName  映射關係:beanName --> 依賴beanName的集合<br/>
 5      * Map between dependent bean names: bean name to Set of dependent bean names.
 6      */
 7     private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
 8 
 9     /**
10      * 保存的是依賴 beanName 之間的映射關係:依賴 beanName - > beanName 的集合
11      * Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
12      */
13     private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
14 
15 public void registerDependentBean(String beanName, String dependentBeanName) {
16         // 獲取beanName
17         String canonicalName = canonicalName(beanName);
18 
19         // 作同步 添加<canonicalName,<dependentBeanName>>到dependentBeanMap中
20         synchronized (this.dependentBeanMap) {
21             Set<String> dependentBeans =
22                     this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
23             if (!dependentBeans.add(dependentBeanName)) {
24                 return;
25             }
26         }
27         // 作同步 添加<canonicalName,<dependentBeanName>>到dependenciesForBeanMap中
28         synchronized (this.dependenciesForBeanMap) {
29             Set<String> dependenciesForBean =
30                     this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
31             dependenciesForBean.add(canonicalName);
32         }
33     }

分析:

這裏就是就是將依賴的beanName關係添加到dependentBeanMap、dependenciesForBeanMap集合中。

#8.最後經過getBean方法實例化依賴bean對象,該方法會在後面進行分析。

各類scope的Bean建立

在通過單例緩存中獲取bean對象、從父類工廠中獲取bean對象、處理依賴bean這三步後,接下來來到對各類scope的bean的建立。首先是單例模式bean對象的建立,咱們知道singleton爲Spring的bean的默認做用域,固然除了singleton以外,還有prototype、request等其餘的scope。

#1.singleton的初始化代碼以下

 1 // AbstractBeanFactory
 2 
 3 if (mbd.isSingleton()) {
 4                     sharedInstance = getSingleton(beanName, () -> {
 5                         try {
 6                             return createBean(beanName, mbd, args);
 7                         } catch (BeansException ex) {
 8                             // Explicitly remove instance from singleton cache: It might have been put there
 9                             // eagerly by the creation process, to allow for circular reference resolution.
10                             // Also remove any beans that received a temporary reference to the bean.
11                             // 顯式從單例緩存中刪除Bean實例
12                             // 由於單例模式下爲了解決循環依賴,可能它已經存在,因此銷燬它
13                             destroySingleton(beanName);
14                             throw ex;
15                         }
16                     });
17                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
18 }

分析:

單例模式bean的初始化是從getSingleton方法開始,固然這裏還有一個重要的createBean方法,該方法咱們留在後面進行分析,首先來看getSingleton方法。

 1 // DefaultSingletonBeanRegistry
 2 
 3 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 4         Assert.notNull(beanName, "Bean name must not be null");
 5         // 作同步
 6         synchronized (this.singletonObjects) {
 7             // 從緩存中檢查一遍
 8             // 由於singlton模式其實已經複用了建立的bean,因此該步驟必須檢查
 9             Object singletonObject = this.singletonObjects.get(beanName);
10             // 爲空,開始進行加載
11             if (singletonObject == null) {
12                 if (this.singletonsCurrentlyInDestruction) {
13                     throw new BeanCreationNotAllowedException(beanName,
14                                                               "Singleton bean creation not allowed while singletons of this factory are in destruction " +
15                                                                       "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
16                 }
17                 if (logger.isDebugEnabled()) {
18                     logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
19                 }
20                 // 加載前置處理 其實就是打一個標記
21                 beforeSingletonCreation(beanName);
22                 // 首先將新的newSingleton設置爲false
23                 boolean newSingleton = false;
24                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
25                 if (recordSuppressedExceptions) {
26                     this.suppressedExceptions = new LinkedHashSet<>();
27                 }
28                 try {
29                     // 初始化bean
30                     // 該過程實際上是調用createBean()方法 這裏是一個回調方法
31                     singletonObject = singletonFactory.getObject();
32                     newSingleton = true;
33                 } catch (IllegalStateException ex) {
34                     // Has the singleton object implicitly appeared in the meantime ->
35                     // if yes, proceed with it since the exception indicates that state.
36                     singletonObject = this.singletonObjects.get(beanName);
37                     if (singletonObject == null) {
38                         throw ex;
39                     }
40                 } catch (BeanCreationException ex) {
41                     if (recordSuppressedExceptions) {
42                         for (Exception suppressedException : this.suppressedExceptions) {
43                             ex.addRelatedCause(suppressedException);
44                         }
45                     }
46                     throw ex;
47                 } finally {
48                     if (recordSuppressedExceptions) {
49                         this.suppressedExceptions = null;
50                     }
51                     // 一堆異常處理後,進行後置處理 移除標誌
52                     afterSingletonCreation(beanName);
53                 }
54                 // 新的bean 加入緩存中
55                 if (newSingleton) {
56                     addSingleton(beanName, singletonObject);
57                 }
58             }
59             return singletonObject;
60         }
61     }

分析(該方法一樣爲同步方法):

該方法其實並未真正建立bean對象,獲取bean對象的核心點在於singletonObject = singletonFactory.getObject(),但該方法是由createBean回調產生的。這裏僅僅是作了一部分準備和預處理步驟:

  • 再次從緩存中檢查bean是否已經加載過,若是緩存中存在則直接返回。
  • beforeSingletonCreation前面已經分析過,記錄加載單例bean的狀態,表示正在被加載。
  • 而後調用singletonFactory.getObject方法實例化bean對象
  • afterSingletonCreation前面也分析過了,移除bean正在被加載的標誌。
  • 將生成的bean對象加入緩存。

DefaultSingletonBeanRegistry#addSingleton

 1     /**
 2      * Cache of singleton objects: bean name to bean instance.
 3      * 存放的是單例 bean 的映射。
 4      * <p>
 5      * 對應關係爲 bean name --> bean instance
 6      */
 7     private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 8 
 9     /**
10      * Cache of singleton factories: bean name to ObjectFactory.<br/>
11      * 存放的是 ObjectFactory,能夠理解爲建立單例 bean 的 factory 。
12      * <p>
13      * 對應關係是 bean name --> ObjectFactory
14      */
15     private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
16 
17     /**
18      * Cache of early singleton objects: bean name to bean instance.<br/>
19      * 存放的是早期的 bean,對應關係也是 bean name --> bean instance。
20      * <p>
21      * 它與 {@link #singletonFactories} 區別在於 earlySingletonObjects 中存放的 bean 不必定是完整。
22      * <p>
23      * 從 {@link #getSingleton(String)} 方法中,咱們能夠了解,bean 在建立過程當中就已經加入到 earlySingletonObjects 中了。
24      * 因此當在 bean 的建立過程當中,就能夠經過 getBean() 方法獲取。
25      * <p>
26      * 這個 Map 也是【循環依賴】的關鍵所在。
27      */
28     private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
29 
30     /**
31      * 存儲已經註冊的單例 進行緩存<br/>
32      * Set of registered singletons, containing the bean names in registration order.
33      */
34     private final Set<String> registeredSingletons = new LinkedHashSet<>(256);    
35 
36     protected void addSingleton(String beanName, Object singletonObject) {
37         synchronized (this.singletonObjects) {
38             this.singletonObjects.put(beanName, singletonObject);
39             this.singletonFactories.remove(beanName);
40             this.earlySingletonObjects.remove(beanName);
41             this.registeredSingletons.add(beanName);
42         }
43     }

分析:

一個put、兩個remove、一個add。

  • 因爲已經實例化了bean,所以須要將單例bean進行緩存,singletonObjects.put。
  • 同理單例BeanFactory和提早曝光的bean也須要移除,singletonFactories.remove和earlySingletonObjects.remove。
  • registeredSingletons.add,已實例化的bean須要進行註冊。

#2.原型模式

 1 if (mbd.isPrototype()) { // 原型模式
 2                     // It's a prototype -> create a new instance.
 3                     Object prototypeInstance = null;
 4                     try {
 5                         // 前置處理
 6                         beforePrototypeCreation(beanName);
 7                         /**
 8                          * 建立bean {@link AbstractAutowireCapableBeanFactory#createBean}
 9                          */
10                         prototypeInstance = createBean(beanName, mbd, args);
11                     } finally {
12                         /**
13                          * 後置處理 與前置處理相反從{@link prototypesCurrentlyInCreation}中移除
14                          */
15                         afterPrototypeCreation(beanName);
16                     }
17                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
18                 }

分析:

原型模式下bean的初始化很簡單,直接建立一個新Bean實例就能夠了。

  • beforePrototypeCreation:記錄加載原型模式bean的加載狀態,前置處理。
  • createBean建立實例對象,該方法很是重要,後續會詳細進行分析。
  • afterPrototypeCreation:移除建立時添加的標誌,後置處理與beforePrototypeCreation方法功能相反。
  • 最後調用getObjectForBeanInstance獲取實例,該方法在【spring源碼分析】IOC容器初始化(六)中已經分析,這裏再也不贅述。

AbstractBeanFactory#beforePrototypeCreation

 1    /**
 2      * 原型模式下存儲beanName的ThreadLocal<br/>
 3      * Names of beans that are currently in creation.
 4      */
 5 private final ThreadLocal<Object> prototypesCurrentlyInCreation =
 6             new NamedThreadLocal<>("Prototype beans currently in creation");
 7 
 8 protected void beforePrototypeCreation(String beanName) {
 9         // 從ThreadLocal中取出對象
10         Object curVal = this.prototypesCurrentlyInCreation.get();
11         if (curVal == null) {
12             // 若是爲空,則設置值
13             this.prototypesCurrentlyInCreation.set(beanName);
14         } else if (curVal instanceof String) {
15             // 若是curVal爲String類型,則進行添加
16             Set<String> beanNameSet = new HashSet<>(2);
17             beanNameSet.add((String) curVal);
18             beanNameSet.add(beanName);
19             this.prototypesCurrentlyInCreation.set(beanNameSet);
20         } else {
21             // 不然將curVal轉換成set集合,添加beanName
22             Set<String> beanNameSet = (Set<String>) curVal;
23             beanNameSet.add(beanName);
24         }
25     }

分析:

這裏的前置處理就是將beanName加入ThreadLocal中,邏輯簡單。

AbstractBeanFactory#afterPrototypeCreation

 1     protected void afterPrototypeCreation(String beanName) {
 2         Object curVal = this.prototypesCurrentlyInCreation.get();
 3         if (curVal instanceof String) {
 4             this.prototypesCurrentlyInCreation.remove();
 5         } else if (curVal instanceof Set) {
 6             Set<String> beanNameSet = (Set<String>) curVal;
 7             beanNameSet.remove(beanName);
 8             if (beanNameSet.isEmpty()) {
 9                 this.prototypesCurrentlyInCreation.remove();
10             }
11         }
12     }

分析:

後置處理與前置處理beforePrototypeCreation正好相反,將標記從ThreadLocal中移除。

#3.其餘做用域

 1 // 得到scopeName對應的Scope對象
 2                     String scopeName = mbd.getScope();
 3                     final Scope scope = this.scopes.get(scopeName);
 4                     if (scope == null) {
 5                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
 6                     }
 7                     try {
 8                         /**
 9                          * 從指定的scope下建立bean
10                          * {@link SimpleThreadScope#get方法}
11                          */
12                         Object scopedInstance = scope.get(beanName, () -> {
13                             beforePrototypeCreation(beanName);
14                             try {
15                                 return createBean(beanName, mbd, args);
16                             } finally {
17                                 afterPrototypeCreation(beanName);
18                             }
19                         });
20                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
21                     } catch (IllegalStateException ex) {
22                         throw new BeanCreationException(beanName,
23                                                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
24                                                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
25                                                         ex);
26                     }
27                 }
28             } catch (BeansException ex) {
29                 cleanupAfterBeanCreationFailure(beanName);
30                 throw ex;
31             }

分析:

其餘做用域bean的建立過程與原型模式的流程同樣,只是獲取bean的方式變成了Scope#get(String name,ObjectFactory<?> objectFactory)。

 1 //  SimpleThreadScope
 2 public Object get(String name, ObjectFactory<?> objectFactory) {
 3         // 獲取scope緩存
 4         Map<String, Object> scope = this.threadScope.get();
 5         Object scopedObject = scope.get(name);
 6         if (scopedObject == null) {
 7             // 這裏getObject也是進行方法回調
 8             scopedObject = objectFactory.getObject();
 9             // 加入緩存
10             scope.put(name, scopedObject);
11         }
12         return scopedObject;
13     }

這裏僅僅是Scope接口的一種實現,該接口還有其餘多種實現,其具體源碼可查看相應實現類:

至此,Bean加載的大體流程已分析完畢,固然本篇文章並未分析一個很重要的函數createBean,該函數留在後續的文章繼續分析。


by Shawn Chen,2019.04.22,下午。

相關文章
相關標籤/搜索