從Spring源碼開始,瞭解ioc,bean生命週期

從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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章