【Spring源碼】17.IOC之ConfigurationClassPostProcessor源碼二:解析各注解

image

3.1 前言

當 需要解析的 BeanDefinition集合收集完畢后梦湘,,接下來就會 遍歷 這個集合里的每一個 BeanDefinition,

解析@Component,@PropertySource盯腌,@ComponentScan, @Import陨瘩,@ImportResource腕够, @Bean级乍,等注解,將各注解的解析結(jié)果存入對應的容器,以待后續(xù)進一步處理燕少。

image

把元數(shù)據(jù)對象和beanName封裝成ConfigurationClass 對象卡者,繼續(xù)往下走

image

會先進行@Conditional注解的判斷蒿囤,如果不符合客们,就會跳過,符合就繼續(xù)往下走

image

3.1 解析 @Component

這個主要是為了 解析該類的內(nèi)部類 材诽,如果內(nèi)部類有 @Component / @ComponentScan / @Import / @ImportResource 注解底挫,需要去解析這個類

image

取出內(nèi)部類,判斷有沒有 @Component / @ComponentScan / @Import / @ImportResource

image

判斷的條件的話還是 和一開始過濾的時候一樣脸侥,會有一個需要解析的注解數(shù)組 來匹配

image

就是這四個注解

image

匹配到了建邓,說明這個內(nèi)部類需要解析,

把他封裝成 ConfigurationClass 對象睁枕,ConfigurationClass importBy 等于他的外部類的ConfigurationClass對象 官边,beanName是為空的

如果是別其他類帶進來的 bean類,此時的ConfigurationClass 的beanName都是為Null.

傳入 這個 ConfigurationClass 對象 外遇,遞歸調(diào)用 processConfigurationClass 去解析它注簿,流程一樣。

image

最后加入到ConfigurationClassParser 對象的configurationClasses map列表中跳仿, 待內(nèi)部類的解析流程走完诡渴,外部類 走完也會加入到 這個map中。

所以菲语,外部類和內(nèi)部類全部解析完妄辩, map列表是這樣的

image

3.2 解析 @PropertySource

@PropertySource 注解 用來 導入 配置文件,將配置文件的信息 納入到配置環(huán)境中

image

根據(jù)配置的 配置文件路徑山上,創(chuàng)建PropertySource對象眼耀,然后加入到Environment對象中

image

加入或者 替換 environment里的 propertySources :配置文件列表
image

3.3 解析 @ComponentScan

該doProcessConfigurationClass方法繼續(xù)往下走

如果該類有 @ComponentScan 注解,同樣的也是 創(chuàng)建一個 掃描器佩憾,掃 @ComponentScan配置的包下 是否有符合的類 需要注冊畔塔,返回 BeanDefinitionHolder集合。

然后調(diào)用 ConfigurationClassUtils.checkConfigurationClassCandidate() 方法判斷 每個 beanDefinition 是否需要被解析鸯屿,和第二點開始哪里判斷的一樣:

是否有@Configuration 注解 + 是否有 @Component / @ComponentScan / @Import / @ImportResource

image

如果需要解析澈吨,遞歸 parse 方法,重新開始解析寄摆,

最后都加入到ConfigurationClassParser 對象的configurationClasses map列表

3.4 解析 @Import

@Import 可以導入一個類谅辣,讓他注冊到spring容器中

image

3.4.1 getImports(sourceClass) ,收集所有@Import 進來的類

這個方法會收集所有的@Import里面配置的類婶恼,封裝成SourceClass對象桑阶,裝進集合中

image
image

如果收集的@Import進來的類不為空柏副,就開始遍歷這些類

3.4.2 如果Import進來的是ImportSelector 接口類型

ImportSelector 接口 : selectImports 會返回一串類的 全限定名稱, 在該解析過程中,這個過程中會被調(diào)用蚣录,并導入這些類

public interface ImportSelector {
   String[] selectImports(AnnotationMetadata importingClassMetadata);
}

會先實例化這個類割择,判斷是不是 DeferredImportSelector 類型的

1. 如果是 DeferredImportSelector 類型

把他加入到ConfigurationClassParser對象的deferredImportSelectorHandler屬性的deferredImportSelectors 集合中

image

2. 如果只是單純的 ImportSelector 類型

調(diào)用ImportSelector接口的selectImports,返回一串類的 全限定名稱數(shù)組萎河,獲取class對象荔泳,封裝成SourceClass集合,遞歸調(diào)用 @Import的解析流程虐杯,導入他們所要導入的類

image

最后都加入到ConfigurationClassParser 對象的configurationClasses map列表

importBy屬性為導入他的類的ConfigurationClass對象

image

3.4.3 如果Import進來的是ImportBeanDefinitionRegistrar 接口類型

1. ImportBeanDefinitionRegistrar 作用

ImportBeanDefinitionRegistrar接口玛歌,如果被導入進來的類是 實現(xiàn)了這個接口,那么在該解析過程中, 會被調(diào)用到 registerBeanDefinitions 方法擎椰,會傳入 導入他的類的 元數(shù)據(jù)AnnotationMetadata對象 和 BeanDefinitionRegistry 對象支子。

public interface ImportBeanDefinitionRegistrar {

   default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   }

}

這個接口用處挺重要的:往往用來導入一些其他的類進來

AnnotationMetadata 對象 可以獲取導入他的類的元數(shù)據(jù),用來獲取注解的配置信息等

BeanDefinitionRegistry對象 : 用來注冊其他類

比如 mybatis的@MapperScan 注解

image

注解mapper接口的BeanDefinition對象到 spring容器中

image

2.實例化該ImportBeanDefinitionRegistrar 實例达舒,放入導入他的類的ConfigurationClass的importBeanDefinitionRegistrars集合里

image

3.4.4 導入的類 沒有實現(xiàn)以上接口

封裝被導入的類為ConfigurationClass對象值朋,遞歸processConfigurationClass 方法,重頭解析被導入的類 的 以上所有注解巩搏。

image

最后都加入到ConfigurationClassParser 對象的configurationClasses map列表中

3.5 解析@ImportResource

解析完@Import注解后昨登,開始解析@ImportResource,@ImportResource可以導入一個applicationContext的xml文件塔猾,注冊里面配置的類

image

3.6 解析@Bean

接下來解析@Bean

image

獲取所有有@Bean注解的方法

image

遍歷篙骡,封裝成BeanMethod對象 ConfigurationClassParser 加到ConfigClass.beanMethods容器中

image

至此,所有的解析工作都已完成丈甸。

3.7 解析結(jié)果與對應存放的容器小結(jié)

1.configurationClassParser的 configurationClasses

有@Component注解的類 和他需要導入類的內(nèi)部類

有 @ComponentScan 注解的類 和他掃描到的 所有類

有 @Import注解的類 和 他導進來的所有類 (除導進來的是DeferredImportSelector,ImportBeanDefinitionRegistrar 接口)

封裝成ConfigurationClass糯俗, 會放在ConfigurationClassParser的 configurationClasses屬性中

private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();

2.ConfigurationClassParser.deferredImportSelectorHandler.deferredImportSelectors

導進來的 DeferredImportSelector接口類

放在 ConfigurationClassParser對象的deferredImportSelectorHandler屬性的deferredImportSelectors 集合中

private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
private class DeferredImportSelectorHandler {

   @Nullable
   private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
  
}

3.ConfigurationClassParser.configurationClasses[n].importBeanDefinitionRegistrars

導進來的 ImportBeanDefinitionRegistrar 接口類型

放在ConfigurationClass的importBeanDefinitionRegistrars

private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars ;

4.ConfigurationClass.beanMethods

@Bean 注解的方法 封裝成 BeanMethod

放在ConfigurationClass的 beanMethods 中

private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();

4.DeferredImportSelector接口的調(diào)用

image

最終也是會調(diào)到我們自己被@Import進來的DeferredImportSelector實現(xiàn)類的selectImports方法里

image

只不過他里面要經(jīng)過 DeferredImportSelector.Group的操作,比較復雜睦擂,礙于文章篇幅得湘,這里就先略過了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末顿仇,一起剝皮案震驚了整個濱河市淘正,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌臼闻,老刑警劉巖鸿吆,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異述呐,居然都是意外死亡惩淳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門乓搬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來思犁,“玉大人代虾,你說我怎么就攤上這事〖ざ祝” “怎么了棉磨?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長学辱。 經(jīng)常有香客問我乘瓤,道長,這世上最難降的妖魔是什么项郊? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任馅扣,我火速辦了婚禮斟赚,結(jié)果婚禮上着降,老公的妹妹穿的比我還像新娘。我一直安慰自己拗军,他們只是感情好任洞,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著发侵,像睡著了一般交掏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刃鳄,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天盅弛,我揣著相機與錄音,去河邊找鬼叔锐。 笑死挪鹏,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的愉烙。 我是一名探鬼主播讨盒,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼步责!你這毒婦竟也來了返顺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蔓肯,失蹤者是張志新(化名)和其女友劉穎遂鹊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔗包,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡秉扑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了气忠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻储。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡赋咽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吨娜,到底是詐尸還是另有隱情脓匿,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布宦赠,位于F島的核電站陪毡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏勾扭。R本人自食惡果不足惜毡琉,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妙色。 院中可真熱鬧桅滋,春花似錦、人聲如沸身辨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽煌珊。三九已至号俐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間定庵,已是汗流浹背吏饿。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蔬浙,地道東北人猪落。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像敛滋,于是被迫代替她去往敵國和親许布。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354