Autowire的實現原理分析,以及Spring如何處理一個Bean的注入

Spring是如何依賴注入的?

實現依賴注入的註解有Spring提供的@Autowire@Value,以及Java提供的@Resource@Inject
在這裏插入圖片描述

源碼追蹤

這裏使用斷點大法,對我們自定義的Bean的創建進行觀察。
首先介紹自定義的Bean結構,我定義了一個Controller,裏面依賴了CommonState和一個Service。
在這裏插入圖片描述
然後我們在AbstractAutowireCapableBeanFactorycreateBean方法中打上斷點。以DEBUG模式運行。
在這裏插入圖片描述
在經過一通其它Bean的創建後終於到我們要觀察的Bean了。

step1 resolveBeanClass()

解析MergedBeanDefinition獲取我們需要的Bean類對象
在這裏插入圖片描述

step2 resolveBeforeInstantiation()

從名字看到是在實例化之前進行解析。Bean的創建分爲Instantiate(實例化)和Initialize(初始化)。
在這裏插入圖片描述
從圖中可以看到會調用applyBeanPostProcessorsBeforeInstantiation(),內部是給InstantiationAwareBeanPostProcessor的實現類一個機會執行postProcessBeforeInstantiation()方法
在這裏插入圖片描述
在這裏插入圖片描述
執行完發現結果爲null。
在這裏插入圖片描述
注意這裏將beforeInstantiationResolved設置爲false了。然後返回null。在這裏插入圖片描述

step3 doCreateBean()

在這裏插入圖片描述
在這裏插入圖片描述
看到進入createBeanInstance(),內部走到instantiateBean()
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
到這一步就很熟悉了,Spring獲取到我們Controller的Class對象,然後通過getDeclaredConstructor()獲取構造器,然後使用工具類BeanUtils::instantiateClass()實例化我們的對象。工具類內部實現就是調用ConstructornewInstance()方法反射獲得實例。
在這裏插入圖片描述
在完成實例化後,需要將實例化的對象包裝成BeanWrapper對象,並進行initBeanWrapper操作,個這個Bean增加Converter功能和註冊PropertyEditorRegistrar
在這裏插入圖片描述
返回到doCreateBean()
在這裏插入圖片描述
調用applyMergedBeanDefinitionPostProcessor(),內部是給MergedBeanDefinitionPostProcessor實現類執行postProcessMergedBeanDefinition(),其中要注意的是CommonAnnotationBeanPostProcessor這個類是用來處理Java提供的依賴注入註解比如@ResourceAutowireAnnotationBeanPostProcessor是用來處理Spring提供的@Autowire,@Value等註解的。
在這裏插入圖片描述
在這裏插入圖片描述
找到AnnotationAutowireBeanPostProcessor
在這裏插入圖片描述
在這裏插入圖片描述
首先調用findAutowiringMetadata(),內部調用buildAutowiringMetadata()
在這裏插入圖片描述
通過doWithLocalField()doWithLocalMethod()獲取依賴的類
在這裏插入圖片描述
這裏發現已經找到statepaperService兩個屬性了,同時type就是類型所在的類名
在這裏插入圖片描述
在這裏插入圖片描述
返回findAutowiringMetadata(),將剛纔解析的依賴元數據添加到ConcurrentHashMap緩存起來。至此,已經完成對指定類的依賴的掃描,並且將依賴做了檢查並放進InjectionMetaData中。

回到doCreateBean()

populateBean()

在這裏插入圖片描述
AutowiredAnnotationBeanPostProcessorpostProcessProperties()
在這裏插入圖片描述
拿到了之前處理的InjectionMetadata,然後inject注入。
在這裏插入圖片描述
進入inject()
在這裏插入圖片描述
在這裏插入圖片描述
獲取依賴的類型
在這裏插入圖片描述
在這裏插入圖片描述
在內部會判斷已經解析的依賴中是否存在這個type,如果不存在則嘗試addCandidateEntry()將這個type通過getBean()獲取Bean對象,然後返回這個依賴實例。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在經過剛纔的依賴對象獲取後,接下來就是注入的過程
在這裏插入圖片描述
在這裏插入圖片描述
最終通過反射Field通過setter進行注入。
在這裏插入圖片描述

總結(圖片版)

在這裏插入圖片描述

總結(文字版)

在Spring啓動後會對ApplicationContext進行refresh,在refresh中先後完成BeanPostProcessor的註冊,然後在finishBeanFactoryInitialization方法中preInitializeSingletionsDefaultListableBeanFactory持有的beanDefinitionNames進行遍歷,然後getBean進行單例Bean注入IOC容器。

來到AbstactAutowireCapableBeanFactorycreateBean方法,在doCreateBean中完成Bean的實例化,依賴注入和初始化。
內部流程是:首先createInstance通過反射獲取Construtor然後newInstance實例化Bean,將Bean包裝成BeanWrapper,然後InitBeanWrapper完成爲這個Bean增加類型轉換器。
然後applyMergedBeanDefinitionPostProcessors裏面CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor會對這個Bean的依賴進行掃描,內部通過doWithLocalFielddoWithLocalMethod獲取依賴的類型以及名稱,然後將各個依賴封裝成InjectedElement,各個InjectedElement統一封裝成InjectionMetadata然後將其緩存起來等populateBean時使用。
populateBean此時纔是依賴注入的關鍵代碼,裏面通過CommonAnntationBeanPostProcessorAutowiredAnnotationBeanPostProcessorpostProcessProperties方法完成依賴注入。
postProcessProperties裏面會獲取剛纔applyMergedBeanDefinitionPostProcessor完成的InjectionMetadata然後調用inject方法,對每一個InjectedElement執行inject,內部通過beanFactory.resolveDependency獲取依賴的值,如果是Bean則通過getBean獲取對應的依賴類在容器中的實例,如果是@Value則會從application.properties中解析對應的值並通過ConversionService轉換成對應的格式。
在完成依賴注入(populateBean)後,會調用initializeBean進行初始化。內部通過applyBeanPostProcessorBeforeInitialization完成前置處理,通過invokeInitMethod完成@BeaninitMethod= xxx()方法的調用,applyBeanPostProcessorAfterInitialization完成後置處理。
這樣一個Bean就創建並初始化完成。
通過addSingleton將這個單例Bean放入DefaultSingletonBeanRegistrysingletonObjects這個ConcurrentHashMap中。

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