容器啟動(dòng)的模板方法
1. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
此方法主要完成對(duì)配置文件中bean定義解析為BeanDefinition的工作,并將BeanDefinition注冊(cè)到registry中.
1.1 刷新BeanFactory
1.1.1 若當(dāng)前已存在BeanFactory,對(duì)其進(jìn)行銷毀和關(guān)閉
1.1.2 創(chuàng)建DefaultListableBeanFactory作為默認(rèn)容器,設(shè)置容器的序列化id并定制一些屬性(allowBeanDefinitionOverriding和allowCircularReferences)
1.1.3 裝載BeanDefinition
1.1.3.1 構(gòu)造一個(gè)XmlBeanDefinitionReader,并對(duì)其進(jìn)行一些設(shè)置
1.1.3.2 BeanDefinition裝載工作委托給XmlBeanDefinitionReader來處理
- 獲取配置文件地址
- 循環(huán)處理每個(gè)配置文件地址來處理BeanDefinition的裝載
?2.1 通過ResourceLoader將配置文件地址解析為Resource
?2.2 通過Resource來裝載BeanDefinition
??2.2.1 將配置文件資源解析為Document
??2.2.2 構(gòu)造一個(gè)BeanDefinitionDocumentReader(實(shí)現(xiàn)類為DefaultBeanDefinitionDocumentReader),將Document解析解析為BeanDefinition并注冊(cè)的工作委托給這個(gè)DefaultBeanDefinitionDocumentReader處理.
??2.2.2.1 構(gòu)造一個(gè)BeanDefinitionParserDelegate,將Document中各個(gè)節(jié)點(diǎn)元素的解析處理工作委托給這個(gè)BeanDefinitionParserDelegate來完成.包括默認(rèn)命名空間節(jié)點(diǎn)元素的解析和自定義命名空間節(jié)點(diǎn)元素的解析(這部分為重點(diǎn),具體放到1.3深入總結(jié)).
1.2 獲取刷新后新的BeanFactory,并將其返回
1.3 默認(rèn)命名空間節(jié)點(diǎn)元素和自定義命名空間節(jié)點(diǎn)元素的解析
以默認(rèn)命名空間的<bean>標(biāo)簽解析為例
1.3.1 BeanDefinitionParserDelegate將Element解析為BeanDefinitionHolder
- 處理beanName和alias
- Element解析為AbstractBeanDefinition
- 生成一個(gè)GenericBeanDefinition(AbstractBeanDefinition的子類),記為bd
- 為bd設(shè)置一些屬性.如scope,lazy-init,depends-on,init-method等等等等.
- 解析該bean元素下的一些子元素屬性設(shè)置
- 構(gòu)造參數(shù)子元素解析(對(duì)應(yīng)以后的構(gòu)造注入,如<constructor-arg index="0" ref="t"/>)
- 屬性子元素解析(對(duì)應(yīng)以后的設(shè)值注入,如<property name="start" value="a"/>),重點(diǎn)分析一下這里屬性注入方式
5.1 處理屬性或子元素(源碼注解:Should only have one child element: ref, value, list, etc.),生成相應(yīng)的對(duì)象并將其返回
5.2 以上述返回的對(duì)象和屬性名構(gòu)造PropertyValue.(這個(gè)類很關(guān)鍵,xml配置bean的方式下,設(shè)值注入的每個(gè)屬性依賴就是通過每個(gè)PropertyValue來實(shí)現(xiàn)的)
5.3 向MutablePropertyValues添加上述PropertyValue.(這是依賴注入另一個(gè)關(guān)鍵類,AbstractBeanDefinition內(nèi)部持有一個(gè)MutablePropertyValues屬性propertyValues,通過這個(gè)屬性保存所有的依賴,MutablePropertyValues內(nèi)部持有一個(gè)List<PropertyValue> propertyValueList,實(shí)際上就是將前面生成的每一個(gè)PropertyValue添加到這個(gè)list中)
- 返回AbstractBeanDefinition
1.3.2 注冊(cè)BeanDefinition以及注冊(cè)別名alias
到這里只是完成了將配置文件中定義的bean解析為Spring為Bean專門定義的數(shù)據(jù)結(jié)構(gòu)BeanDefinition,還未完成實(shí)例化和依賴的注入,只是將數(shù)據(jù)解析和準(zhǔn)備完成.
2. invokeBeanFactoryPostProcessors(beanFactory);
實(shí)現(xiàn)BeanFactoryPostProcessor接口的后置處理器的處理邏輯調(diào)用,BeanFactoryPostProcessor是對(duì)BeanDefinition的后置處理(此時(shí)bean還未進(jìn)行實(shí)例化和依賴注入,只是以解析后的BeanDefinition形式存在)
3. registerBeanPostProcessors(beanFactory);
注冊(cè)BeanPostProcessor,這里只是注冊(cè),還未實(shí)際調(diào)用
4. finishBeanFactoryInitialization(beanFactory);
這里完成bean的實(shí)例化,依賴注入,后置處理等等一些列操作.關(guān)鍵方法beanFactory.preInstantiateSingletons();
4.1 獲取所有的注冊(cè)的beanName,循環(huán)遍歷處理以完成實(shí)例化和依賴注入
4.1.1 獲取BeanDefinition
4.1.2 對(duì)于滿足條件:非抽象&&單例&&非延遲初始化的BeanDefinition,通過getBean方法完成實(shí)例化并獲取Bean
4.1.2.1 從單例緩存中獲取實(shí)例
4.1.2.2 如果取得實(shí)例不為空,若該實(shí)例為普通Bean,直接返回;若為FactoryBean,嘗試從FactoryBean緩存中獲取,存在則返回,否則的話最終通過FactoryBean的getObject方法獲取對(duì)象,并存緩存.(getObjectForBeanInstance方法源碼注解:Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.)
4.1.2.3 如果取得實(shí)例為空(重點(diǎn)分支流程)
- 獲取父容器,若滿足條件父容器不為空&&當(dāng)前容器不包含該beanName的BeanDefinition,返回調(diào)用父容器的getBean方法的結(jié)果,否則不執(zhí)行這一步,繼續(xù)向下執(zhí)行
- 獲取BeanDefinition
- 獲取解析后存于BeanDefinition中的依賴(String[]),循環(huán)處理每個(gè)依賴
- 判斷是否循環(huán)depends-on關(guān)系,是則拋出異常
- 注冊(cè)依賴
- 遞歸調(diào)用getBean方法,先處理依賴的Bean(也就是先遞歸到最底層處理沒有任何依賴的Bean,在一層一層返回上層處理,這樣保證了依賴的底層Bean會(huì)先被實(shí)例化)
- 如果BeanDefinition中的數(shù)據(jù)記錄的該bean是單例的,那么最終通過createBean方法(該方法由AbstractAutowireCapableBeanFactory實(shí)現(xiàn))來完成Bean的初始化,依賴注入,各種后置處理等等工作(這里只分析單例情況,prototype情況不分析了)
- 為BeanPostProcessors提供返回代理而不是目標(biāo)bean實(shí)例的機(jī)會(huì).(源碼注釋:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.)
1.1 對(duì)InstantiationAwareBeanPostProcessor接口的實(shí)現(xiàn)類調(diào)用其前置方法postProcessBeforeInstantiation,只要有一個(gè)接口實(shí)現(xiàn)類的postProcessBeforeInstantiation方法調(diào)用成功(即返回的結(jié)果不為null),后面其他接口實(shí)現(xiàn)類就不再執(zhí)行
1.2 在上面1.1執(zhí)行成功的前提下,執(zhí)行所有的BeanPostProcessor的后置處理方法postProcessAfterInitialization - doCreateBean方法(重要方法)
2.1 createBeanInstance方法,使用適當(dāng)?shù)膶?shí)例化策略為指定的bean創(chuàng)建新實(shí)例:工廠方法彤敛,構(gòu)造函數(shù)自動(dòng)裝配或簡(jiǎn)單實(shí)例化(源碼注釋:Create a new instance for the specified bean, using an appropriate instantiation strategy:factory method, constructor autowiring, or simple instantiation.).該方法返回一個(gè)BeanWrapper,BeanWrapper中通過一個(gè)內(nèi)部屬性object來持有bean,此時(shí)的bean只是初步創(chuàng)建,還未進(jìn)行依賴注入
2.2 執(zhí)行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
2.3 populateBean方法用來完成依賴注入
?2.3.1 獲取BeanDefinition的PropertyValues
?2.3.2 調(diào)用InstantiationAwareBeanPostProcessors的處理方法postProcessAfterInstantiation,為任何InstantiationAwareBeanPostProcessors提供在設(shè)置屬性之前修改bean狀態(tài)的機(jī)會(huì).例如,這可以用于支持現(xiàn)場(chǎng)注入的樣式(源碼注釋:Give any InstantiationAwareBeanPostProcessors the opportunity to modify the state of the bean before properties are set. This can be used, for example, to support styles of field injection.)
?2.3.3 autowireByName或者autowireByType,這里分析一下autowireByType
??2.3.3.1 找到需要依賴注入的屬性氮块,不包括基本類型和String等這種簡(jiǎn)單的類型
??2.3.3.2 處理依賴,獲取被注入bean
??2.3.3.3 將上述bean添加到MutablePropertyValues的propertyValueList中(從原List中遍歷去除同名PropertyValue以保證是同一個(gè)屬性,合并屬性并返回;若遍歷原List時(shí)沒有同一名稱的屬性,則直接添加到List中)
??2.3.3.4 調(diào)用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法進(jìn)行一些后置處理(注解注入@autowired的實(shí)現(xiàn)就是通過這里AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法來實(shí)現(xiàn)的)
??2.3.3.5 applyPropertyValues應(yīng)用屬性,完成注入.
2.4 initializeBean方法的執(zhí)行,初始化給定的bean實(shí)例,應(yīng)用工廠回調(diào)以及init方法和bean后處理器(源碼注釋:Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.)
?2.4.1 invokeAwareMethod方法調(diào)用,完成一些Aware接口方法處理,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
?2.4.2 BeanPostProcessor的postProcessBeforeInitialization處理方法
?2.4.3 invokeInitMethods方法調(diào)用,執(zhí)行一些init方法
?2.4.4 BeanPostProcessor的postProcessAfterInitialization處理方法
- 為BeanPostProcessors提供返回代理而不是目標(biāo)bean實(shí)例的機(jī)會(huì).(源碼注釋:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.)
注:
Spring Bean的實(shí)例化和初始化兩個(gè)階段的主要作用:
1聘鳞、實(shí)例化Instantiation—-實(shí)例化的過程是一個(gè)創(chuàng)建Bean的過程,即調(diào)用Bean的構(gòu)造函數(shù),單例的Bean放入單例池中,可理解為createBeanInstance方法階段初步創(chuàng)建的bean.
2、初始化Initialization—-初始化的過程是一個(gè)賦值的過程,即調(diào)用Bean的setter,設(shè)置Bean的屬性,可理解為依賴注入階段