從Spring源碼開始,瞭解ioc,bean生命週期
該文章內容所使用的spring版本爲:spring-core-5.2.4.RELEASE.jar
1. 這裏我們開始從Spring容器的創建開始講起,瞭解refresh方法都做了什麼,不會非常細緻的走每一步,重載和實現太多了,這裏主要講xml的形式
我們先創建spring上下文對象,它繼承了AbstractApplicationContext,AbstractApplicationContext有多種子類實現,xml配置方式,註解方式等,用來獲取bean的定義信息(BeanDefinition)
如果是註解方式創建上下文使用掃描配置類,或掃描包的形式獲取BeanDefinition
AnnotationConfigApplicationContext
掃描到之後直接註冊到BeanFactory的map裏
DefaultListableBeanFactory
如果是Xml方式,調用setConfigLocationsh獲取一個或多個xml配置文件
ClassPathXmlApplicationContext
解析佔位符,替換一些屬性,這裏和註解方式不一樣,並沒有直接將xml去直接解析爲BeanDefinition,然後註冊到BeanFactory的map裏
無論是哪一種實現都要調用refresh刷新容器(所以好多面試都是會問到這個東西),接下來就看一下里面都幹了什麼
1 refresh進來之後的第一個方法,做了一些初始化時間和設置標誌位,實例化Environment並且做了一些校驗
AbstractApplicationContext <<< 當前位置
2 refresh進來後二個方法關鍵,實例化了beanFactory,創建BeanDefinitionReader加載BeanDefinition
Loads the bean definitions via an XmlBeanDefinitionReader.
AbstractXmlApplicationContext <<< 當前位置
走到這裏,用IO讀取了配置文件,包裝成document對象
Load bean definitions from the specified XML file.
XmlBeanDefinitionReader <<< 當前位置
從document中get出element對象循環去解析
Register each bean definition within the given root {@code } element.
DefaultBeanDefinitionDocumentReader <<< 當前位置
(重點) 一路向下,將解析出來的BeanDefinition放入DefaultListableBeanFactory的map中
DefaultListableBeanFactory <<< 當前位置
2. 看到這裏就知道了,ClassPathXmlApplicationContext通過Io讀取Xml文件,並且解析爲BeanDefinition,然後在Bean在實例化之前,將Bean定義信息存放在DefaultListableBeanFactory的map當中保留,Bean工廠也已經實例化完成,後續的方法會需要傳入這個工廠對象
上面一直在提BeanDefinition,下面就例舉一些BeanDefinition接口中的方法
//是否單例
boolean isSingleton();
//是否多例
boolean isPrototype();
//是否懶加載
boolean isLazyInit();
//是否是主要對象
boolean isPrimary();
//初始化方法名稱
String getInitMethodName();
//銷燬方法名稱
String getDestroyMethodName();
3 refresh進來後 第三個方法就是對剛實例化好的bean工廠設置一些屬性,需要注意的是這裏設置了一個beanPostProcessor(增強器),實例化了一個ApplicationListenerDetector將當前上下文對象傳遞進去,之後會判斷是否是ApplicationListener的實現,是的話加入上下文中
AbstractApplicationContext <<< 當前位置
4 refresh進來後 第四個方法是空方法,需要自定義實現BeanFactoryPostProcessor接口,重寫postProcessBeanFactory方法,將實例化完成的BeanFactory傳入,並對其進行一些增強處理操作
5 refresh進來後 第五個方法 就是按照一定的優先級,去調用所有註冊到容器中的BeanFactoryPostProcessor的postProcessBeanFactory方法
First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
6 refresh進來後 第六個方法將經過反覆加工的bean工廠,和當前上下文對象(applicationContext)傳入,註冊BeanPostProcessors(和BeanFactoryPostProcessor 不要搞混了,不是一個東西 ,BeanPostProcessor用的和問的比較多,對bean初始化前後增強就是靠它,後面會講)
(這裏提醒下,beanPostProcessor聽上去是後置處理器,不要以爲是後置處理器就是初始化之後 執行的類,要點進去看裏面的方法,有一個befor和after,也就是前後都是這個類使用方法區分前後執行的)
PostProcessorRegistrationDelegate <<< 當前位置
根據類型在之前註冊好存放BeanDefinition的map中去找符合的對象,返回BeanName
接下來還是按照排序和優先級分類註冊到集合中,最後順序循環集合添加到BeanFactory中的List beanPostProcessors = new CopyOnWriteArrayList<>();
First, register the BeanPostProcessors that implement PriorityOrdered.
Next, register the BeanPostProcessors that implement Ordered.
Finally, re-register all internal BeanPostProcessors.
refresh進來後 第七 ,第8 個方法放一起說吧,
第七個方法註冊瞭解析消息(比如i18n國際化需要MessageSource)
第八個方法註冊了多播器,Spring提供的事件機制中的ApplicationListener監聽器需要註冊在這裏
9 refresh進來後 第九個方法是一個空方法,Spring預留給子類使用,子類可以實現通過重寫onRefresh做一些操作
10 refresh進來後 第十個方法,根據類型在之前註冊好存放BeanDefinition的map中去找符合的ApplicationListener對象
看着是不是有點眼熟,上面的beanPostProcessor一樣,通過類型獲取beanName並放入集合中
(到這裏的bean都未實例化哦,依然是均爲BeanDefinition)
AbstractApplicationContext <<< 當前位置
11 refresh進來後 第十一個方法 finishBeanFactoryInitialization,終於到了關鍵的實例化bean的方法
直接跳到這行,進入實現 beanFactory.preInstantiateSingletons();
DefaultListableBeanFactory <<< 當前位置
進入getBean方法中,再進入doGetBean方法中
找到createBean方法,然後進入doCreateBean ,所有do method纔是實際執行的內容
在這個方法裏實例化了bean的時候並填充beanPostProcessor
Central method of this class: creates a bean instance,
populates the bean instance, applies post-processors, etc.
AbstractAutowireCapableBeanFactory <<< 當前位置
實例化bean,幷包裝爲BeanWrapper
通過構造器的反射創建bean的實例
populateBean方法,注入屬性(ioc)
Populate the bean instance in the given BeanWrapper with the property values
根據名稱和類型裝配
解析pvs注入bean
找到initializeBean方法,(初始化bean前後方法的執行順序就在這裏) (生命週期)
1⃣️ 調用beanPostProcessor的postProcessBeforeInitialization方法,前置增強
2⃣️ 反射調用initMethod方法,初始化
3⃣️ 調用beanPostProcessor的postProcessAfterInitialization方法後置增強
4⃣️ registerDisposableBeanIfNecessary註冊銷燬器DisposableBeanAdapter
12 最後一個方法finishRefresh完成容器刷新
最後把beanFactory的對於生命週期的註釋放在下面
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
* <ol>
* <li>BeanNameAware's {@code setBeanName}
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
* <li>BeanFactoryAware's {@code setBeanFactory}
* <li>EnvironmentAware's {@code setEnvironment}
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean's {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>
*
* <p>On shutdown of a bean factory, the following lifecycle methods apply:
* <ol>
* <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* <li>DisposableBean's {@code destroy}
* <li>a custom destroy-method definition
* </ol>