目錄
- 前言
- 閱讀準備
- 閱讀指引
- 閱讀建議
- 課程內容
- 一、SpringIOC之實例化
- 1.1 簡單回顧
- 1.2 概念回顧
- 1.3 核心方法講解
- 二、方法講解
- 2.1 AbstractBeanFactory#getMergedLocalBeanDefinition:合并BeanDefinition
- 2.2 AbstractAutowireCapableBeanFactory#createBean:創建Bean
- 2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass:加載類
- *2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:【實例化前】入口
- 2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation:【實例化前】真正干活的地方
- 2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization:第一次可能調用【初始化后】
- 2.7 AbstractAutowireCapableBeanFactory#doCreateBean:【實例化】入口(包括后續的實例化過程)
- *2.8 AbstractAutowireCapableBeanFactory#createBeanInstance:實例化
- 2.8.1 Supplier創建對象
- 2.8.2 工廠方法創建對象
- 2.8.3 構造方法創建對象
- 2.9 AbstractAutowireCapableBeanFactory#autowireConstructor:推斷構造方法
- 2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors:BeanDefinition后置處理
- 2.11 AbstractAutowireCapableBeanFactory#populateBean:屬性注入(包含:實例化后)
- 方法總結后
- 三、實例化邏輯流程圖
- 學習總結
前言
閱讀準備
由于Spring源碼分析是一個前后聯系比較強的過程,而且這邊分析,也是按照代碼順序講解的,所以不了解前置知識的情況下,大概率沒辦法看懂當前的內容。所以,特別推薦看看我前面的文章(自上而下次序):
- Spring底層核心原理解析【學習難度:★★☆☆☆】
- 手寫簡易Spring容器過程分析【學習難度:★★☆☆☆】
- Spring之底層架構核心概念解析【學習難度:★★★☆☆,重要程度:★★★★★】
- Bean的生命周期流程圖【學習難度:☆☆☆☆☆,重要程度:★★★★★】
- Spring之Bean的生命周期源碼解析——階段一(掃描生成BeanDefinition)【學習難度:★★☆☆☆,重要程度:★★★☆☆】
(PS:特別是《Bean的生命周期流程圖》,幫大家【開天眼】,先了解下流程。畢竟【通過業務了解代碼,遠比通過代碼了解業務簡單的多】!!!!)
(PS:特別是《Bean的生命周期流程圖》,幫大家【開天眼】,先了解下流程。畢竟【通過業務了解代碼,遠比通過代碼了解業務簡單的多】!!!!)
(PS:特別是《Bean的生命周期流程圖》,幫大家【開天眼】,先了解下流程。畢竟【通過業務了解代碼,遠比通過代碼了解業務簡單的多】!!!!)
閱讀指引
我們在上一節課已經說到過了,本次Spring源碼剖析的總入口是new AnnotationConfigApplicationContext("org.tuling.spring");
,這里就不再重復解釋了。本節課要說的內容,是SpringIOC的實例化,我們這里直接給到入口吧,調用鏈如下:(調用鏈比較深,不要糾結細枝末節)
- AbstractApplicationContext#refresh:刷新方法,不用在意
- AbstractApplicationContext#finishBeanFactoryInitialization:在這里實例化所有剩余的(非lazy-init)單例
- DefaultListableBeanFactory#preInstantiateSingletons:在這里實例化所有剩余的(非lazy-init)單例(上面的方法,核心干活的方法就是這里)
- DefaultListableBeanFactory#getBean:獲取Bean的方法
- AbstractBeanFactory#doGetBean:返回指定bean的一個實例,它可以是共享的,也可以是獨立的
- 上面這個
AbstractBeanFactory#doGetBean
里面的一段局部代碼寫的回調方法,如下:
// 如果是單例創建bean實例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
- AbstractAutowireCapableBeanFactory#createBean:這個類的中心方法:創建一個bean實例,填充bean實例,應用后處理器,等等。
如上面的調用鏈所示,最后一個方法,才是我們本次要研究的核心方法。而且通過注釋,我想大家也看到了,這個方法不單單干了實例化的工作,還有屬性填充、各種后置處理器等。(PS:哈哈,同學們,我知道這個【實例化】調用鏈挺深的,但是大家不要煩惱,只要切記【不要糾結那些細枝末節】那一切都OK,我們老老實實地跟著主線來研究就好,畢竟這些才是核心)
閱讀建議
- 看源碼,切記糾結細枝末節,不然很容易陷進去。正常來說,看主要流程就好了
- 遇到不懂的,多看看類注釋或者方法注釋。Spring這種優秀源碼,注釋真的非常到位
- 如果你是idea用戶,多用F11的書簽功能。
- Ctrl + F11 選中文件 / 文件夾,使用助記符設定 / 取消書簽 (必備)
- Shift + F11 彈出書簽顯示層 (必備)
- Ctrl +1,2,3…9 定位到對應數值的書簽位置 (必備)
課程內容
一、SpringIOC之實例化
這里說的【實例化】,是指單例的實例化,原型prototype不包含在內
1.1 簡單回顧
大家知道,實例化的過程是怎樣的嗎?哈,我知道大部分的同學可能都不會知道。所以呢,我希望大家真的要有去看過《 Bean的聲明周期流程圖》,因為,通過【代碼去理解業務】,遠遠比【通過業務理解代碼】難得多!直接看個圖吧,起碼咱得知道【實例化到底干了什么,有哪些步驟】,我們才能更好的去研究。
如上圖所示,實例化包含了:合并BeanDefinition、加載類、實例化之前、推斷構造方法、實例化、BeanDefinition的后置處理、實例化后等,這些關鍵步驟。這就是我們本篇文章研究的核心!!
1.2 概念回顧
在這個【實例化】過程中,涉及到了一些Spring底層設計的概念,我在上一個筆記里面有大概介紹過Spring底層概念的一些講解,不記得的同學記得回去翻一翻。
主要涉及的概念有:
- BeanDefinition(設計圖紙):BeanDefinition表示Bean定義,BeanDefinition中存在很多屬性用來描述一個Bean的特征
- BeanPostProcessor(Spring重要的拓展點):Bean的后置處理器,對Bean做拓展操作。我們前面說過,
BeanPostProcessor
提供了【初始化前/后】兩個拓展方法。但是這里,Spring內部對這個接口做了很多拓展,新增了一些繼承自BeanPostProcessor
的子類或者子接口。在實例化階段,主要用到的接口如下:InstantiationAwareBeanPostProcessor
,直譯過來就是:能感知實例化的Bean后置處理器。而這個繼承自BeanPostProcessor
,顯然也具備這【初始化前/后】兩個拓展方法。另外,通過InstantiationAwareBeanPostProcessor
的名字大家也能猜到了,它肯定是具有對【實例化】階段拓展的能力的。接口定義在后面。SmartInstantiationAwareBeanPostProcessor
:直譯過來就是:智能的,能感知實例化的Bean后置處理器。在這個接口中,拓展了InstantiationAwareBeanPostProcessor
接口,新增了幾個函數,其中就包括了推斷構造的實現。另外,這是一個框架內部使用接口。接口定義在后面。MergedBeanDefinitionPostProcessor
:直譯過來就是:合并BeanDefinition的后置處理器。運行時用于合并bean定義的后處理器回調接口。接口定義在后面。
InstantiationAwareBeanPostProcessor接口定義如下:
/*** BeanPostProcessor的子接口,用于添加實例化前回調,以及實例化后但顯式屬性設置或自動生成之前的回調。* 通常用于抑制特定目標bean的默認實例化,例如創建具有特殊TargetSources的代理(池化目標、惰性初始化目標等),或者實現額外的注入策略,如字段注入。* 注:此接口為專用接口,主要供框架內部使用。建議盡可能實現普通的BeanPostProcessor接口。* 自:* 1.2* 參見:* org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.setCustomTargetSourceCreators, org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator* 作者:* 于爾根·霍勒,羅德·約翰遜*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {/*** 在目標bean實例化之前應用這個BeanPostProcessor。返回的bean對象可能是要使用的代理而不是目標bean,從而有效地抑制目標bean的默認實例化。* 如果此方法返回一個非空對象,則bean創建過程將會中斷。應用的唯一進一步處理是來自配置的BeanPostProcessors的postProcessAfterInitialization回調。* 這個回調將應用于帶有bean類的bean定義,以及工廠方法定義,在這種情況下,返回的bean類型將在這里傳遞。* 后置處理器可以實現擴展的SmartInstantiationAwareBeanPostProcessor接口,以便預測它們將在這里返回的bean對象的類型。* 默認實現返回null。* 參數:* beanClass——要實例化的bean的類* beanName—bean的名稱* 返回:* 要公開的bean對象,而不是目標bean的默認實例,或者為空,繼續進行默認實例化* 拋出:* BeansException -在錯誤的情況下* 參見:* postProcessAfterInstantiation, org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(), org.springframework.beans.factory.support.AbstractBeanDefinition.getFactoryMethodName()*/@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}/*** 在bean通過構造函數或工廠方法實例化之后,但在Spring屬性填充(來自顯式屬性或自動裝配)發生之前執行操作。* 這是在Spring自動裝配開始之前對給定bean實例執行自定義字段注入的理想回調。* 默認實現返回true。* 參數:* Bean—已創建的Bean實例,其屬性尚未設置* beanName—bean的名稱* 返回:* 如果應該在bean上設置屬性,則為True;如果應該跳過屬性人口,則為False。正常的實現應該返回true。返回false還將阻止在此bean實例上調用任何后續的InstantiationAwareBeanPostProcessor實例。* 拋出:* BeansException -在錯誤的情況下* 參見:* postProcessBeforeInstantiation*/default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}/*** 在工廠將給定的屬性值應用到給定的bean之前,對它們進行后處理,不需要任何屬性描述符。* 如果實現提供自定義postProcessPropertyValues實現,則應該返回null(默認值),否則則返回pvs。在該接口的未來版本中(刪除了postProcessPropertyValues),默認實現將直接返回給定的pv。* 參數:* PVS—工廠將要應用的屬性值(永遠不會為空)* bean——已創建的bean實例,但其屬性尚未設置* beanName—bean的名稱* 返回:* 應用于給定bean的實際屬性值(可以是傳入的PropertyValues實例),或者null,它繼續處理現有屬性,但特別地繼續調用postProcessPropertyValues(需要為當前bean類初始化PropertyDescriptors)。* 拋出:* BeansException -在錯誤的情況下* 自:* 5.1* 參見:* postProcessPropertyValues*/@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}/*** 在工廠將給定屬性值應用到給定bean之前,對它們進行后處理。允許檢查是否滿足所有依賴項,例如基于bean屬性設置器上的“Required”注釋。* 還允許替換要應用的屬性值,通常通過基于原始PropertyValues創建新的MutablePropertyValues實例,添加或刪除特定值。* 默認實現按原樣返回給定的pv。* 棄用* 從5.1開始,支持postProcessProperties(PropertyValues, Object, String)* 參數:* PVS—工廠將要應用的屬性值(永遠不會為空)* PDS——目標bean的相關屬性描述符(忽略了依賴類型——工廠專門處理的依賴類型——已經過濾掉了)* bean——已創建的bean實例,但其屬性尚未設置* beanName—bean的名稱* 返回:* 應用于給定bean的實際屬性值(可以是傳入的PropertyValues實例),或者為null以跳過屬性填充* 拋出:* BeansException -在錯誤的情況下* 參見:* postProcessProperties, org.springframework.beans.MutablePropertyValues*/@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}
SmartInstantiationAwareBeanPostProcessor接口定義如下:
/*** 擴展了InstantiationAwareBeanPostProcessor接口,添加了一個回調函數,用于預測被處理bean的最終類型。* 注:此接口為專用接口,主要供框架內部使用。一般來說,應用程序提供的后處理器應該簡單地實現普通的BeanPostProcessor接口,或者從InstantiationAwareBeanPostProcessorAdapter類派生。即使在點發布版本中,也可能向該接口添加新方法。* 自:* 2.0.3* 參見:* InstantiationAwareBeanPostProcessorAdapter* 作者:* Juergen hoel*/
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {/*** 預測這個處理器的postProcessBeforeInstantiation回調最終返回的bean的類型。* 默認實現返回null。* 參數:* beanClass—bean的原始類beanName—bean的名稱* 返回:* bean的類型,如果不可預測,則為空* 拋出:* BeansException -在錯誤的情況下*/@Nullabledefault Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}/*** 確定要為給定bean使用的候選構造函數。* 默認實現返回null。* 參數:* beanClass—bean的原始類(不為空)beanName—bean的名稱* 返回:* 候選構造函數,如果未指定,則為空* 拋出:* BeansException -在錯誤的情況下*/@Nullabledefault Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)throws BeansException {return null;}/*** 獲取對指定bean的早期訪問的引用,通常是為了解析循環引用。* 這個回調讓后處理器有機會盡早公開包裝器——也就是說,在目標bean實例完全初始化之前。暴露的對象應該等同于postProcessBeforeInitialization / postProcessAfterInitialization所暴露的對象。請注意,此方法返回的對象將用作bean引用,除非后處理器返回與所述后處理回調不同的包裝器。換句話說:那些處理后回調可能最終公開相同的引用,或者返回那些后續回調的原始bean實例(如果受影響的bean的包裝器已經為對該方法的調用構建了,那么默認情況下它將作為最終bean引用公開)。* 默認實現按原樣返回給定的bean。* 參數:* bean—原始bean實例beanName—bean的名稱* 返回:* 要作為bean引用公開的對象(通常將傳入的bean實例作為默認值)* 拋出:* BeansException -在錯誤的情況下*/default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}
}
MergedBeanDefinitionPostProcessor接口定義如下:
/*** 運行時用于合并bean定義的后處理器回調接口。BeanPostProcessor實現可以實現這個子接口,以便對合并的bean定義(原始bean定義的處理副本)進行后處理,Spring BeanFactory使用合并的bean定義來創建bean實例。* 例如,postProcessMergedBeanDefinition方法可以對bean定義進行內省,以便在對bean的實際實例進行后處理之前準備一些緩存的元數據。也允許修改bean定義,但只允許修改用于并發修改的定義屬性。本質上,這只適用于在RootBeanDefinition本身上定義的操作,而不適用于其基類的屬性。* 自:* 2.5* 參見:* org.springframework.beans.factory.config.ConfigurableBeanFactory.getMergedBeanDefinition* 作者:* Juergen hoel*/
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/*** 對指定bean的給定合并bean定義進行后處理。* 參數:* beanDefinition—為bean合并的bean定義beanType—托管bean實例的實際類型beanName—bean的名稱* 參見:* AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors*/void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);/*** 通知指定名稱的bean定義已被重置,并且此后處理器應清除受影響bean的所有元數據。* 默認實現為空。* 參數:* beanName—bean的名稱* 自:* 5.1* 參見:* DefaultListableBeanFactory.resetBeanDefinition*/default void resetBeanDefinition(String beanName) {}
}
這里還是有一點想要提醒各位的,BeanPostProcessor
是被Spring定義為【鉤子】的,而鉤子,很多時候都是為了改變系統原有行為的。這種改變,通常體現在:對Bean生命周期的影響,或者某個生命周期完成對象的改變等等。(這么說有點晦澀難懂,通俗點講就是:Bean可能不會經過完整生命周期,比如【實例化前】之后,直接就跳到【初始化后】了,沒有經過原本定義的【實例化】、【實例化后】、【其他后置處理】等;或者,原本初始化動作是Spring幫我門完成的,但是由于我們自己介入了,Spring就不幫我們初始化了,而是按照程序員意愿)
文章鏈接:
《【Spring專題】Spring之底層架構核心概念解析》
1.3 核心方法講解
整個IOC實例化的主干過程,主要涉及了【2個類,11個核心方法】。下面,我們將會按照調用次序,依次講解各個方法。
二、方法講解
我們在上面說到過,這里的實例化過程包含了:合并BeanDefinition、加載類、實例化之前、推斷構造方法、實例化、BeanDefinition的后置處理、實例化后等關鍵步驟。所以,在整個調用鏈上,基本上就是干了這些事情。
我們前面說過,本次的實例化代碼入口如下:
// 如果是單例創建bean實例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
2.1 AbstractBeanFactory#getMergedLocalBeanDefinition:合并BeanDefinition
方法調用鏈:AbstractBeanFactory#doGetBean里面調用的
全路徑:org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
方法注釋:返回合并的RootBeanDefinition,如果指定的bean對應于子bean定義,則遍歷父bean定義。
我們在上節課最后的地方提到過這個,這邊就不重復講了,但是,他是算在實例化過程里面的,嘻嘻
2.2 AbstractAutowireCapableBeanFactory#createBean:創建Bean
方法調用鏈:AbstractBeanFactory#doGetBean里面調用的
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
方法注釋:這個類的中心方法:創建一個bean實例,填充bean實例,應用后處理器,等等。
源碼如下:
@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// 步驟一:加載類Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// 不用管這個try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// 步驟二:實例化前Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// 步驟三:創建BeanObject beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}
方法解讀:上面代碼老長一段,trt-catch
占了一半,啊哈哈。 這里面的步驟就三個,下面也會講到。
- resolveBeanClass:加載類
- resolveBeforeInstantiation:實例化前
- doCreateBean:真正創建Bean的地方
2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass:加載類
PS:不算很重要,知道有這個步驟就好
方法調用鏈:由2.2的createBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeanClass
方法注釋:這個類的中心方法:創建一個bean實例,填充bean實例,應用后處理器,等等。
源碼如下:
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)throws CannotLoadBeanClassException {if (mbd.hasBeanClass()) {return mbd.getBeanClass();}if (System.getSecurityManager() != null) {return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());}else {return doResolveBeanClass(mbd, typesToMatch);}
}
方法解讀:這個代碼外層挺簡單的,也許大家對比System.getSecurityManager() != null
這個比較難理解而已。這是Spring內部的一個安全管理器,很多時候都是不開啟的。后面也會出現大量這種代碼,反正遇到這個就直接看else
的邏輯就好了。至于里層的doResolveBeanClass
源碼如下:
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)throws ClassNotFoundException {// 步驟一:獲取默認的類加載器ClassLoader beanClassLoader = getBeanClassLoader();ClassLoader dynamicLoader = beanClassLoader;boolean freshResolve = false;// 步驟二:在我們這個調用鏈上不會走這里,因為typesToMatch為nullif (!ObjectUtils.isEmpty(typesToMatch)) {ClassLoader tempClassLoader = getTempClassLoader();if (tempClassLoader != null) {dynamicLoader = tempClassLoader;freshResolve = true;if (tempClassLoader instanceof DecoratingClassLoader) {DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;for (Class<?> typeToMatch : typesToMatch) {dcl.excludeClass(typeToMatch.getName());}}}}// 步驟三String className = mbd.getBeanClassName();if (className != null) {// 步驟3.1:這里也不用怎么看,這是Spring表達式解析的東西。Spring表達式這個東西我們用的很少(類似EL表達式,這樣來理解)Object evaluated = evaluateBeanDefinitionString(className, mbd);if (!className.equals(evaluated)) {if (evaluated instanceof Class) {return (Class<?>) evaluated;}else if (evaluated instanceof String) {className = (String) evaluated;freshResolve = true;}else {throw new IllegalStateException("Invalid class name expression result: " + evaluated);}}if (freshResolve) {if (dynamicLoader != null) {try {// 步驟3.2 加載類return dynamicLoader.loadClass(className);}catch (ClassNotFoundException ex) {if (logger.isTraceEnabled()) {logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);}}}return ClassUtils.forName(className, dynamicLoader);}}// 步驟四:正常來說走的是這里。使用默認的類加載器加載類return mbd.resolveBeanClass(beanClassLoader);}
方法解讀:在這里,大體分為4個步驟。步驟一就是獲取類加載器,往里追蹤會發現,實際上調用的是ClassUtils.getDefaultClassLoader()
方法。里面的代碼挺簡單的,獲取原則如下:(需要一點JVM底子才懂,不了解也無所謂)
- 優先返回當前線程中的ClassLoader
- 線程中類加載器為null的情況下,返回ClassUtils類的類加載器
- 如果ClassUtils類的類加載器為空,那么則表示是Bootstrap類加載器加載的ClassUtils類,那么則返回系統類加載器
步驟二,就是第一個if
,在我們這里的調用鏈上是不會進來這里的,因為typeToMatch
是null;
步驟三,可看可不看,一般也不會進來這里。這是Spring表達式解析的東西。Spring表達式這個東西我估計大部分人都沒用過吧…(類似EL表達式,這樣來理解)
步驟四,正常來說會執行到這里,然后在這里進行類加載,并且通過反射獲得class對象,代碼如下所示:
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {String className = getBeanClassName();if (className == null) {return null;}Class<?> resolvedClass = ClassUtils.forName(className, classLoader);this.beanClass = resolvedClass;return resolvedClass;}
*2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:【實例化前】入口
(PS:終于來到這里了,這才是核心考點)
方法調用鏈:由2.2的createBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
方法注釋:應用實例化前的后處理器,解析指定bean是否存在實例化前的快捷方式。
源碼如下:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}
方法解讀:代碼短短的幾行。首先通過hasInstantiationAwareBeanPostProcessors
看看是否有InstantiationAwareBeanPostProcessors
。有,則調用對應的【實例化前】方法,即applyBeanPostProcessorsBeforeInstantiation
(這里才是真正干活的地方,后面介紹)。
這里有一個細節,那就是applyBeanPostProcessorsBeforeInstantiation
如果返回的對象不為空,則直接調用applyBeanPostProcessorsAfterInitialization
走bean的【初始化后】方法了。這說明Bean的生命周期被改變!!而且,如果這里的Bean有值的話,外層直接返回創建成功了,不會繼續往下走了,如下所示:(2.2的createBean調用處代碼)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {return bean;
}
2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation:【實例化前】真正干活的地方
方法調用鏈:由2.4的resolveBeforeInstantiation調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
方法注釋:將InstantiationAwareBeanPostProcessors應用到指定的bean定義(通過類和名稱),調用它們的postProcessBeforeInstantiation方法。如果返回不為空,則無需Spring幫我們實例化了
源碼如下:
@Nullableprotected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}return null;}
方法解讀:這里終于出現我們之前說的核心InstantiationAwareBeanPostProcessor
了。老樣子,遍歷所有的InstantiationAwareBeanPostProcessor
,然后調用postProcessBeforeInstantiation()
。這里只要找到一個InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation()
返回不為空,則直接停止遍歷。
這個方法其實隱含的意思是:在Spring幫我們實例化之前,Spring會先去找找看,用戶有沒有對當前beanName對應的class有自己的實例化想法,如果有,則Spring就不幫我們創建了。
2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization:第一次可能調用【初始化后】
方法調用鏈:由2.4的resolveBeforeInstantiation調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
方法注釋:應用初始化后方法。通常調用此方法的時候,會認為已經經過了屬性填充、初始化等
源碼如下:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
方法解讀:看,這里直接獲取所有BeanPostProcessor
接口,然后應用postProcessAfterInitialization()
方法。這里有個空判斷,是接口要求這么做的。返回null表示不想繼續執行剩余的BeanPostProcessor
接口
2.7 AbstractAutowireCapableBeanFactory#doCreateBean:【實例化】入口(包括后續的實例化過程)
方法調用鏈:由2.2的createBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
方法注釋:AbstractAutowireCapableBeanFactory這個類的中心方法:創建一個bean實例,填充bean實例,應用后處理器,等等
源碼很長,就不截取了。在這里個方法里面,主要干了4件事情:
- 實例化(推斷構造方法、實例化)
- BeanDefinition的后置處理
- 屬性注入(實例化后、屬性注入)(對的,你沒看錯,【實例化后】是在屬性注入這個方法里面被調用的)
- 初始化
方法解讀:正如方法注釋說的,這里【創建一個bean實例,填充bean實例,應用后處理器】等等。這意味著,在這里包含了【實例化】過程中剩余的==【推斷構造方法、實例化、BeanDefinition的后置處理、實例化后等】==步驟。另外,下一個章節會說的【IOC屬性填充】、【IOC-Aware回調】、【IOC初始化】等階段入口其實也是在這個方法中。
*2.8 AbstractAutowireCapableBeanFactory#createBeanInstance:實例化
方法調用鏈:由2.7的doCreateBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
方法注釋:AbstractAutowireCapableBeanFactory這個類的中心方法:創建一個bean實例,填充bean實例,應用后處理器,等等
源碼如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 步驟一:再次確保類已經被加載Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}// 步驟二:使用Supplier創建對象Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 步驟三:工廠方法創建對象if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}// 步驟四:推斷構造方法Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 步驟五:實例化return instantiateBean(beanName, mbd);}
方法解讀:這里在實例化Bean的時候,采用了多種方式。如:
2.8.1 Supplier創建對象
Supplier,直譯:供應商。
首先判斷BeanDefinition中是否設置了Supplier,如果設置了則調用Supplier的get()得到對象。得直接使用BeanDefinition對象來設置Supplier,比如:
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {@Overridepublic Object get() {return new UserService();}
});
context.registerBeanDefinition("userService", beanDefinition);
2.8.2 工廠方法創建對象
如果沒有設置Supplier,則檢查BeanDefinition中是否設置了factoryMethod,也就是工廠方法,有兩種方式可以設置factoryMethod,比如:
方式一:
<bean id="userService" class="com.zhouyu.service.UserService" factory-method="createUserService" />
對應的UserService類為:
public class UserService {public static UserService createUserService() {System.out.println("執行createUserService()");UserService userService = new UserService();return userService;}public void test() {System.out.println("test");}}
方式二:
<bean id="commonService" class="com.zhouyu.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService" />
對應的CommonService的類為:
public class CommonService {public UserService createUserService() {return new UserService();}
}
Spring發現當前BeanDefinition方法設置了工廠方法后,就會區分這兩種方式,然后調用工廠方法得到對象。
值得注意的是,我們通過@Bean所定義的BeanDefinition,是存在factoryMethod和factoryBean的,也就是和上面的方式二非常類似,@Bean所注解的方法就是factoryMethod,AppConfig對象就是factoryBean。如果@Bean所所注解的方法是static的,那么對應的就是方式一。
2.8.3 構造方法創建對象
RT。
2.9 AbstractAutowireCapableBeanFactory#autowireConstructor:推斷構造方法
方法調用鏈:由2.7的createBeanInstance調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor
方法注釋:推斷構造方法,并且創建對象。
代碼好長,我就不截取了。這里的代碼看不看都還好,主要還是理解流程跟原則就好。
- 如果一個類只有一個構造方法,不管這個構造方法是有參還是無參,Spring都會使用這個構造方法創建對象
- 如果有多個構造方法,則看有沒有無參構造方法。因為無參構造方法有默認的含義,若有,則選擇無參的構造方法創建對象;
- 如果有多個構造方法,且沒有無參,則看構造方法上是否有@Autowired注解,有就選擇,沒有就報錯
額外的,在推斷構造方法邏輯中除開會去選擇構造方法以及查找入參對象意外,會還判斷是否在對應的類中是否存在使用**@Lookup注解**了方法。如果存在則把該方法封裝為LookupOverride對象并添加到BeanDefinition中。
?
在實例化時,如果判斷出來當前BeanDefinition中沒有LookupOverride,那就直接用構造方法反射得到一個實例對象。如果存在LookupOverride對象,也就是類中存在@Lookup注解了的方法,那就會生成一個代理對象。
@Lookup注解就是方法注入,使用demo如下:
@Component
public class UserService {private OrderService orderService;public void test() {OrderService orderService = createOrderService();System.out.println(orderService);}@Lookup("orderService")public OrderService createOrderService() {return null;}}
2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors:BeanDefinition后置處理
方法調用鏈:由2.7的doCreateBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
方法注釋:將MergedBeanDefinitionPostProcessors應用于指定的bean定義,調用它們的postProcessMergedBeanDefinition方法。
源碼如下:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}
方法解讀:Bean對象實例化出來之后,接下來就應該給對象的屬性賦值了。在真正給屬性賦值之前,Spring又提供了一個擴展點,即當前的MergedBeanDefinitionPostProcessors
。這里的主要難點還是,這種類型的BeanPostProcessor
的應用場景,可能才是大家比較關心的。那你們覺得,這里的主要應用場景應該是什么呢?其實,按照Spring的生命周期來說,他現在提供給你的拓展點,只能是【實例化】階段后的生命周期了,畢竟過去已經發生的已經沒辦法改變。所以,我們可以在這里,干預【初始化】這個階段,如下示例:
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Object newUser = context.getBean("user");System.out.println(newUser);
}// 聲明bean
@Component
public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void myInit() {System.out.println("這是我自己指定的初始化方法");}
}// 聲明一個MergedBeanDefinitionPostProcessor,然后改變了User這個Bean的初始化方法
@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("user")) {beanDefinition.setInitMethodName("myInit");}}
}
PS:在Spring源碼中,AutowiredAnnotationBeanPostProcessor
就是一個MergedBeanDefinitionPostProcessor
,它的postProcessMergedBeanDefinition()
中會去查找注入點,并緩存在AutowiredAnnotationBeanPostProcessor
對象的一個Map中(injectionMetadataCache),為依賴注入做準備。
2.11 AbstractAutowireCapableBeanFactory#populateBean:屬性注入(包含:實例化后)
(PS:屬性注入不是我們這里需要關注的地方,但因為【實例化后】在這個方法里面,所以就只能點進來了)
方法調用鏈:由2.7的doCreateBean調用過來
全路徑:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
方法注釋:使用來自bean定義的屬性值在給定的BeanWrapper中填充bean實例(屬性填充/依賴注入)。
populateBean中關鍵源碼如下:
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}
方法解讀:在處理完BeanDefinition后,Spring又設計了一個擴展點:InstantiationAwareBeanPostProcessor
的postProcessAfterInstantiation()
,比如:
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)) {UserService userService = (UserService) bean;userService.test();}return true;}
}
上述代碼就是對userService所實例化出來的對象進行處理。這個擴展點,在Spring源碼中基本沒有怎么使用。估計是為了后面拓展做準備
方法總結后
以后可能不這么寫了,挺麻煩的。我這樣圈關鍵方法跟鏈路的原因,純粹是想加深自己的印象,我也不知道放出來給大伙看,你們能否學習到什么。
三、實例化邏輯流程圖
學習總結
- 學習了實例化的過程
- 學習了實例化過程中用到的2種【Bean后置處理器】:
InstantiationAwareBeanPostProcessor
和MergedBeanDefinitionPostProcessor
以及他們內部的一些方法