spring容器的核心IOC和Aop,其中ioc控制反轉,就是spring容器幫助程序員創建對象以及維護對象之間的依賴關系,
DI依賴注入就是其中非常重要的一環,我們平常使用比較多的就是set注入、構造器注入,使用@Autowired、@Resource注解注入等,
下面我們就分析一下spring源碼是怎么實現的。
一:set注入
准備環境:
在spring-context.xml中配置student的bean信息
<bean id="student" class="com.hello.model.Student"> <property name="height" value="100"></property> <property name="weight" value="300"></property> </bean>
運行結果:
下面從源碼來看一下set注入:
在解析spring-context.xml的時候,解析bean元素,會解析到子元素property,這個部分在默認標簽解析那節分析過,然后把屬性值封裝
到MultablePropertyValues對象上,放到BeanDefinition對象上面緩存
進入polulateBean方法中:
從BeanDefinition對象中拿到PropertyValues屬性:
應用屬性值:
剛才我們使用的是set注入,直接注入的字符串,如果使用ref,注入對象,會如何處理?
看一下下面標注的這行代碼,根據原始值獲取value值:
如果是字符串類型,則直接獲取字符串的值,上面的value=“100”,就是走到這里
如果是引用類型,會走到如下分支代碼:
根據參數名稱,到beanFactory容器中獲取bean對象,其他的步驟和字符串的value一樣
二:構造器注入
構造器注入的方式就是上一節分析的有參數構造器的創建過程,在實例化的過程中就實現了注入
<bean id="student" class="com.hello.model.Student"> <constructor-arg index="0" value="100"/> <constructor-arg index="1" value="200"/> </bean>
運行結果:
分析過程見上一節實例化對象的分析
三:@Autowired注解注入依賴
准備工作:
運行結果:
這里面有兩個比較重要的對象AutowireAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor
首先要埋點,創建BeanDefinition對象,然后注冊到BeanDefinitionMaps緩存中,看一下ComponentScanBeanDefinitionParser類
注冊注解輔助相關組件:
將AutowiredAnnotationBeanPostProcessor封裝成BeanDefinition對象,注冊到BeanDefinitionMaps緩存中
注冊完成后,就要實例化對象,實例化的動作實在refresh方法的registerBeanPostProcessors方法中完成的,這一步在之前分析BeanPostProcessor接口的時候已經分析過
這一步完成后,AutowiredAnnotationBeanPostProcessor對象就被注冊到了BeanPostProcessors集合中,以備后面攔截使用
注冊beanDefinition完成,實例化對象完成,下面就要看具體的攔截使用。
我們來看一下搜集過程:
搜集類上的注解信息:
搜集字段和方法上的注解信息:
因為我們的@Autowired注解是在屬性上,所以我們看一下解析字段屬性的代碼塊
搜集到Cat cat 屬性上面有Autowired注解信息
到這里類clazz的注解屬性信息搜集完畢,放入緩存中
回到populateBean方法中,設置bean對象的屬性
從緩存中取出注解元數據信息:
注入依賴對象:
到容器singletonObjects緩存中查找或者實例化對象,然后反射實現對象注入
尋找依賴:
實例化依賴的bean對象,然后在上一步反射實現注入,到這里Autowired注解實現依賴注入的過程就結束了。
總結:依賴注入是spring容器IOC能夠實現的核心功能,spring容器幫助我們維護對象之間的關系。
set注入:主要是在解析的時候property屬性封裝到BeanDefinition對象上,然后在pupulateBean設置屬性的時候,
從BeanDefinition的MultiPropertyValues中取出數據,然后通過反射設置到對象上,如果設置的值為bean,那么在解析的時候
會用到一個runtimeRefence,然后在populateBean的時候再通過getBean實例化對象
構造器注入,在創建對象的時候,從BeanDefinition的ConstructArgs中取出數據,反射尋找有參數構造器,然后創建對象實例
@Autowired注解主要實現依賴於AutowiredAnnotationBeanPostProcesor,埋點,注冊BeanDefinition,實例化,搜集注解信息,攔截根據屬性getBean尋找bean對象,反射注入。