1 定義bean的方式
常見的定義Bean的方式有:
通過xml的方式,例如:
?
通過注解的方式,在Class上使用@Component等注解,例如
?
通過在@Configuration類下的@Bean的方式,例如
?
雖然這三種定義Bean的方式不一樣,對應的處理細節也不一樣,但是從大的邏輯上來看,都是一樣。主要的流程如下圖: 最關鍵的就是問題就是這么去找到定義Bean的方式,然后生成BeanDefinition后注冊到Spring上下文中,由Spring自動創建Bean的實例。
2 BeanDefinition
BeanDefinition是一個接口,用來描述一個Bean實例,例如是SINGLETON還是PROTOTYPE,屬性的值是什么,構造函數的參數是什么等。簡單來說,通過一個BeanDefinition我們就可以完成一個Bean實例化。 BeanDefinition及其主要的子類:
下面簡單說一下各個子類:
RootBeanDefinition和ChildBeanDefinition: 這2個BeanDefinition是相對的關系,自Spring 2.5 出來以后,已經被GenericBeanDefinition代替。因為這樣強迫我們在編寫代碼的時候就必須知道他們之間的關系。
GenericBeanDefinition: 相比于RootBeanDefinition和ChildBeanDefinition在定義的時候就必須硬編碼,GenericBeanDefinition的優點可以動態的為GenericBeanDefinition設置parent。
AnnotatedBeanDefinition:看名字就是知道是用來讀取通過注解定義Bean。
3 通過xml文件定義Bean
通過xml定義Bean是最早的Spring定義Bean的方式。因此,怎么把xml標簽解析為BeanDefinition(), 入口是在org.springframework.beans.factory.xml.XmlBeanDefinitionReader這個類,但是實際干活的是在org.springframework.beans.factory.xml.BeanDefinitionParserDelegate。代碼很多,但實際邏輯很簡單,就是解析Spring定義的 等標簽 。
4 通過@Component等Spring支持的注解加載Bean
如果要使用@Component等注解定義Bean,一個前提條件是:有或者@ComponentScan注解。但這2個方式還是有一點點區別:
4.1
由于是一個xml標簽,因此是在解析xml,生成的類org.springframework.context.annotation.ComponentScanBeanDefinitionParser,關鍵代碼:
?
4.2 @ComponentScan
注解對應生成的類是org.springframework.context.annotation.ComponentScanAnnotationParser 其實最后實際干活的還是ClassPathBeanDefinitionScanner這個。ComponentScanAnnotationParser類的生成是伴隨著@Configuration這個注解處理過程中(意思說@ComponentScan必須和@Configuration一起使用)。而處理@Configuration其實是org.springframework.context.annotation.ConfigurationClassPostProcessor。是不是感覺有點繞。
其實簡單來說,在處理@Configuration的時候發現有@ComponentScan注解,就會生成ComponentScanAnnotationParser去掃描@Component注解
4.3 ClassPathBeanDefinitionScanner
上面說到了,無論注解還是標簽的方式,最后都會交給ClassPathBeanDefinitionScanner這個類來處理,這個類做的就是1.掃描basePackage下所有class,如果有@Component等注解,讀取@Component相關屬性,生成ScannedGenericBeanDefinition,注冊到Spring中。
5 通過@Bean方式
前面說了@ComponentScan是在@Configuration處理過程中的一環,既然@Bean注解也是必須和@Configuration一起使用,那么說明@Bean的處理也是在@Configuration中,其實最后是交給ConfigurationClassBeanDefinitionReader這個類來處理的,關鍵代碼:
?
6 把BeanDefinition實例化
前面分別說了怎么把不同定義Bean的方式轉換為BeanDefinition加入到Spring中去(確切來說是保持在BeanFactory的BeanDefinitionMap中),實例是在ApplicationContext最后階段,關鍵代碼在DefaultListableBeanFactory中
?
通過getBean最后最后實例的代碼,在AbstractAutowireCapableBeanFactory中
?
從上面初始化可以看出,InitializeBean和BeanPostProcessors的調用順序
7 總結
綜上分析,Spring加載Bean其實大的思想都是一樣的,先讀取相關信息生成BeanDefinition,然后通過BeanDefinition初始化Bean。如果知道了上面了套路以后,就可以清楚怎么自定義Xml標簽或者自定義注解向Spring中注入Bean。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/lizo/p/6759080.html
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态