Spring中,可通過方法參數或實例屬性來進行注入。Spring中對LookUp註解的處理。
開始
上一次,我們聊到了AutowiredFieldElement中的inject方法,聊到了獲取value。那麼,這次,我們就聊聊它是怎麼獲取value的。
InjectionPoint
沿著inject的邏輯,我們找到了resolvedCachedArgument方法,然後,我們看到了一個新的類,DependencyDescriptor。這是幹什麼的呢?溯源而上。
InjectionPoint,直譯為注入點。這個類也確實是用來描述一個注入點的,即解決從什麼位置注入的問題。注入點通常有以下兩種形式:
1. 一個實例方法的參數,該實例方法可以是構造方法,也可以是其它方法,注入點中,會保存該參數及其上的相關註解等信息。
2. 實例成員屬性,注入點會保存該成員及其上的相關註解等信息。
也就是說,注入點由注入位置和輔助信息構成。注入位置通常是某方法的參數或某成員屬性,輔助信息則由註解負責描述。我們也看到,InjectionPoint中,幾個成員變量,分別是MethodParameter類型,Field類型和Annotion數組。
DependencyDescriptor
DependencyDescriptor,依賴描述符,該類繼承於InjectionPoint,在注入點相關信息的基礎上,增加了依賴相關的其它一些必要信息,如依賴是否必要,是否飢餓加載,嵌套級別等。
這裡,沒什麼要詳細說的,具體方法等用到再說,補充一些關於飢餓加載的知識。
加載就是把需要用到的目標載入進來,在Spring中,指的是獲取依賴的Bean,並注入。那什麼時候注入呢?就引出了關於加載方式的幾個名詞,除飢餓加載外,還有延遲加載和顯示加載。
飢餓加載,加載某Bean的同時,會將該Bean中所依賴的Bean同時加載進來。很符合飢餓這個名詞,我已經餓了,所以,有吃的趕緊上,哪怕我暫時還沒空吃呢。
延遲加載,又叫懶加載,我飢餓加載剛好不同,加載Bean的同時,並不會同時加載它的依賴,只有在相關依賴需要用到時,才會加載。
顯示加載,事實上,顯示加載不能稱之為一種加載方式,它只是通過相關代碼,顯示的告訴程序要何時加載,要飢餓加載還是延遲加載。
留個思考題:飢餓加載和延遲加載的意義分別在哪裡?
resolvedCachedArgument
resolvedCachedArgument,直譯為解決緩存參數。回到AutowiredFieldElement的inject方法,發現,當cached為true時,就會走該方法。參數是一個bean名稱和cachedFieldValue。在resolvedCachedArgument方法中,我們發現,cachedFieldValue可以轉換成一個依賴描述符類,轉換後,通過調用BeanFactory的resolveDependency方法,來獲取相應的依賴。
當cached為false時,會自己通過field和required參數來構造依賴描述符,構建完成後,再調用resolvedCachedArgument獲取依賴。獲取成功好,會根據相關結果和配置,調用registerDependentBeans,該方法最終調用了BeanFactory的registerDependentBean方法,主要是把依賴的Bean註冊到Bean工廠中。
ShortcutDependencyDescriptor
ShortcutDependencyDescriptor,快捷依賴描述符。當cached為false時,還用到了AutowiredAnnotationBeanPostProcessor中的另一個內部類,ShortcutDependencyDescriptor。這個類的作用是通過一個shortcut,以幫助從Bean工廠中,更快找到需要的依賴。
AutowiredAnnotationBeanPostProcessor中,還有另外一個內部類,AutowiredMethodElement,它和AutowriedFieldElement的意義和用法基本是相同的。只是一個用於欄位,另一個用於方法。
至此,我們聊完了AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,再往下,我們發現postProcessPropertyValues打上了過期標誌,而predictBeanType沒什麼內容,所以,我們直接來到了determineCandidateConstructors方法。
determineCandidateConstructors
determineCandidateConstructors,直譯為確定候選人的構造函數。這個方法比較長,但是我們發現,它其實可以分成兩個部分,其中,第一部分是對LookUp註解的處理。之前我們聊過,LookUp註解可以幫助我們避免在單例模式Bean中依賴原型Bean時,出現的原型變成單例的問題,那麼,這部分的邏輯就是遍歷Bean中,每個依賴上的LookUp註解,並根據LookUp的value,形成一個LookUpOverride,並把該Override,添加到Bean定義的MethodOverrides集合中。
這裡,補充一下LookUpOverride是啥。LookUpOverride繼承於MethodOverride,MethodOverride又實現了BeanMetadataElement接口。BeanMetadataElement直譯為Bean元數據元素,只有一個getSource方法,用於返回Bean的來源。
MethodOverride,直譯為方法重寫,是一個抽象類,主要定義了方法名稱這個類屬性。
LookupOverride,直譯為LookUp重寫。主要是為了記錄某個被LookUp註解標記的注入。
第二部分,正式獲取候選構造方法列表,這部分內容,我們下次再聊。
相關
Spring Bean相關的常用註解(1)
Spring Bean相關的常用註解(2)
Spring Bean相關的常用註解(3)
Spring中的注入是通過反射來完成的
Spring中BeanDefinition的繼承體系