Spring是如何依賴注入的?
實現依賴注入的註解有Spring提供的@Autowire
,@Value
,以及Java提供的@Resource
,@Inject
源碼追蹤
這裏使用斷點大法,對我們自定義的Bean的創建進行觀察。
首先介紹自定義的Bean結構,我定義了一個Controller,裏面依賴了CommonState和一個Service。
然後我們在AbstractAutowireCapableBeanFactory
的createBean
方法中打上斷點。以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()
實例化我們的對象。工具類內部實現就是調用Constructor
的newInstance()
方法反射獲得實例。
在完成實例化後,需要將實例化的對象包裝成BeanWrapper
對象,並進行initBeanWrapper
操作,個這個Bean增加Converter功能和註冊PropertyEditorRegistrar
。
返回到doCreateBean()
調用applyMergedBeanDefinitionPostProcessor()
,內部是給MergedBeanDefinitionPostProcessor
實現類執行postProcessMergedBeanDefinition()
,其中要注意的是CommonAnnotationBeanPostProcessor
這個類是用來處理Java提供的依賴注入註解比如@Resource
,AutowireAnnotationBeanPostProcessor
是用來處理Spring
提供的@Autowire,@Value
等註解的。
找到AnnotationAutowireBeanPostProcessor
首先調用findAutowiringMetadata()
,內部調用buildAutowiringMetadata()
通過doWithLocalField()
和doWithLocalMethod()
獲取依賴的類
這裏發現已經找到state
和paperService
兩個屬性了,同時type就是類型所在的類名
返回findAutowiringMetadata()
,將剛纔解析的依賴元數據添加到ConcurrentHashMap
緩存起來。至此,已經完成對指定類的依賴的掃描,並且將依賴做了檢查並放進InjectionMetaData
中。
回到doCreateBean()
populateBean()
AutowiredAnnotationBeanPostProcessor
的postProcessProperties()
拿到了之前處理的InjectionMetadata
,然後inject
注入。
進入inject()
獲取依賴的類型
在內部會判斷已經解析的依賴中是否存在這個type,如果不存在則嘗試addCandidateEntry()
將這個type通過getBean()
獲取Bean對象,然後返回這個依賴實例。
在經過剛纔的依賴對象獲取後,接下來就是注入的過程
最終通過反射Field通過setter進行注入。
總結(圖片版)
總結(文字版)
在Spring啓動後會對ApplicationContext
進行refresh
,在refresh
中先後完成BeanPostProcessor
的註冊,然後在finishBeanFactoryInitialization
方法中preInitializeSingletions
對DefaultListableBeanFactory
持有的beanDefinitionNames
進行遍歷,然後getBean
進行單例Bean注入IOC容器。
來到AbstactAutowireCapableBeanFactory
的createBean
方法,在doCreateBean
中完成Bean的實例化,依賴注入和初始化。
內部流程是:首先createInstance
通過反射獲取Construtor
然後newInstance
實例化Bean,將Bean包裝成BeanWrapper
,然後InitBeanWrapper
完成爲這個Bean增加類型轉換器。
然後applyMergedBeanDefinitionPostProcessors
裏面CommonAnnotationBeanPostProcessor
和AutowiredAnnotationBeanPostProcessor
會對這個Bean的依賴進行掃描,內部通過doWithLocalField
和doWithLocalMethod
獲取依賴的類型以及名稱,然後將各個依賴封裝成InjectedElement
,各個InjectedElement
統一封裝成InjectionMetadata
然後將其緩存起來等populateBean
時使用。
populateBean
此時纔是依賴注入的關鍵代碼,裏面通過CommonAnntationBeanPostProcessor
和AutowiredAnnotationBeanPostProcessor
的postProcessProperties
方法完成依賴注入。
postProcessProperties
裏面會獲取剛纔applyMergedBeanDefinitionPostProcessor
完成的InjectionMetadata
然後調用inject
方法,對每一個InjectedElement
執行inject
,內部通過beanFactory.resolveDependency
獲取依賴的值,如果是Bean則通過getBean
獲取對應的依賴類在容器中的實例,如果是@Value
則會從application.properties
中解析對應的值並通過ConversionService轉換成對應的格式。
在完成依賴注入(populateBean
)後,會調用initializeBean
進行初始化。內部通過applyBeanPostProcessorBeforeInitialization
完成前置處理,通過invokeInitMethod
完成@Bean
中initMethod= xxx()
方法的調用,applyBeanPostProcessorAfterInitialization
完成後置處理。
這樣一個Bean就創建並初始化完成。
通過addSingleton
將這個單例Bean放入DefaultSingletonBeanRegistry
的singletonObjects
這個ConcurrentHashMap
中。