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

image

3.1 前言

当 需要解析的 BeanDefinition集合收集完毕后,,接下来就会 遍历 这个集合里的每一个 BeanDefinition,

解析@Component,@PropertySource,@ComponentScan, @Import,@ImportResource, @Bean,等注解,将各注解的解析结果存入对应的容器,以待后续进一步处理。

image

把元数据对象和beanName封装成ConfigurationClass 对象,继续往下走

image

会先进行@Conditional注解的判断,如果不符合,就会跳过,符合就继续往下走

image

3.1 解析 @Component

这个主要是为了 解析该类的内部类 ,如果内部类有 @Component / @ComponentScan / @Import / @ImportResource 注解,需要去解析这个类

image

取出内部类,判断有没有 @Component / @ComponentScan / @Import / @ImportResource

image

判断的条件的话还是 和一开始过滤的时候一样,会有一个需要解析的注解数组 来匹配

image

就是这四个注解

image

匹配到了,说明这个内部类需要解析,

把他封装成 ConfigurationClass 对象,ConfigurationClass importBy 等于他的外部类的ConfigurationClass对象 ,beanName是为空的

如果是别其他类带进来的 bean类,此时的ConfigurationClass 的beanName都是为Null.

传入 这个 ConfigurationClass 对象 ,递归调用 processConfigurationClass 去解析它,流程一样。

image

最后加入到ConfigurationClassParser 对象的configurationClasses map列表中, 待内部类的解析流程走完,外部类 走完也会加入到 这个map中。

所以,外部类和内部类全部解析完, map列表是这样的

image

3.2 解析 @PropertySource

@PropertySource 注解 用来 导入 配置文件,将配置文件的信息 纳入到配置环境中

image

根据配置的 配置文件路径,创建PropertySource对象,然后加入到Environment对象中

image

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

3.3 解析 @ComponentScan

该doProcessConfigurationClass方法继续往下走

如果该类有 @ComponentScan 注解,同样的也是 创建一个 扫描器,扫 @ComponentScan配置的包下 是否有符合的类 需要注册,返回 BeanDefinitionHolder集合。

然后调用 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 会返回一串类的 全限定名称, 在该解析过程中,这个过程中会被调用,并导入这些类

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

会先实例化这个类,判断是不是 DeferredImportSelector 类型的

1. 如果是 DeferredImportSelector 类型

把他加入到ConfigurationClassParser对象的deferredImportSelectorHandler属性的deferredImportSelectors 集合中

image

2. 如果只是单纯的 ImportSelector 类型

调用ImportSelector接口的selectImports,返回一串类的 全限定名称数组,获取class对象,封装成SourceClass集合,递归调用 @Import的解析流程,导入他们所要导入的类

image

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

importBy属性为导入他的类的ConfigurationClass对象

image

3.4.3 如果Import进来的是ImportBeanDefinitionRegistrar 接口类型

1. ImportBeanDefinitionRegistrar 作用

ImportBeanDefinitionRegistrar接口,如果被导入进来的类是 实现了这个接口,那么在该解析过程中, 会被调用到 registerBeanDefinitions 方法,会传入 导入他的类的 元数据AnnotationMetadata对象 和 BeanDefinitionRegistry 对象。

public interface ImportBeanDefinitionRegistrar {

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

}

这个接口用处挺重要的:往往用来导入一些其他的类进来

AnnotationMetadata 对象 可以获取导入他的类的元数据,用来获取注解的配置信息等

BeanDefinitionRegistry对象 : 用来注册其他类

比如 mybatis的@MapperScan 注解

image

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

image

2.实例化该ImportBeanDefinitionRegistrar 实例,放入导入他的类的ConfigurationClass的importBeanDefinitionRegistrars集合里

image

3.4.4 导入的类 没有实现以上接口

封装被导入的类为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 解析结果与对应存放的容器小结

1.configurationClassParser的 configurationClasses

有@Component注解的类 和他需要导入类的内部类

有 @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接口的调用

image

最终也是会调到我们自己被@Import进来的DeferredImportSelector实现类的selectImports方法里

image

只不过他里面要经过 DeferredImportSelector.Group的操作,比较复杂,碍于文章篇幅,这里就先略过了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,387评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,845评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,091评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,308评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,662评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,795评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,008评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,743评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,466评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,687评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,181评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,531评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,177评论 3 239
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,126评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,862评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,734评论 2 274