SpringIoc初始化及加载过程(一)

​​源码解析(基于AnnotationConfigApplicationContext分析)

调用构造方法

this()用来初始化​注解的bean定义扫描器和classpath的bean定义扫描器

register(annotatedClasses)用来注册主配置类

关键代码都在refresh()方法中

一)初始化事件多播器解析(initApplicationEventMulticaster)

首先判断IOC容器中是否包含applicationEventMulticaster事件多播器的Bean name

有的话从容器中获取多播器,没有的话创建一个多播器并注册到容器中


二)把容器中的监听器注册到多播器上(registerListeners)


第一个for循环把系统的监听器注册到多播器上

第二个for循环把自己实现的监听器注册到多播器上

最后将早期堆积的事件(由于之前没有多播器)发布出去,这里的早期事件是指在onRefresh()方法中实现的,该方法在SpringBoot中有使用

发布事件步骤↓

获取所有监听器循环发布,如果支持线程池则交由线程池执行,不支持则同步进行发布

​调用监听器实现的onApplicationEvent()方法发布事件

三)调用BeanFactory后置处理器(invokeBeanFactoryPostProcessors)

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

>org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

>org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors(这里各种筛选排序略,其中调用

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,nbspregistry))

>org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

在这里创建了解析器,进入parse解析方法

>org.springframework.context.annotation.ConfigurationClassParser#parse

>org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass

>org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

这里就厉害了

@PropertySource@ComponentScan@Import@Bean还有超类等等都在这里解析

a)@ComponentScan

处理@ComponentScan注解这里,解析@ComponentScans注解,封装成每个componentscan信息的AnnotationAttributes对象,并循环使用componentScanParser进行解析

>org.springframework.context.annotation.ComponentScanAnnotationParser#parse

创建类路径下的bean定义扫描器

这里就可以解释为什么在useDefaultFilters为true的时候会注册所有@Component注解的bean

然后解析出来componentScan的各项配置属性并执行doScan

>org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan

>org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponentsnbsp(查找候选组件)

>org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent(判断是否是候选组件)

​如果是排除内容返回false如果是包含内容返回true

>org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isConditionMatch(查看是否能通过@Conditional判断)

回到doScan方法最后循环筛选到的Bean定义信息,用BeanName生成器生成BeanName,最后注册当前Bean定义信息

回到doProcessConfigurationClass方法

​循环调用扫描出来的bean中导入的bean定义信息

b)@Import

这里有三种类型,一种实现了ImportSelector接口的,一种实现了ImportBeanDefinitionRegistrar接口的,最后一种普通引入

c)@Bean

retrieveBeanMethodMetadata解析出来@Bean注解的方法元信息

回到org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

​>package org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions

>org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass

在这里对@Import进来的类和@Bean注解方法的Bean注册到容器中

总结:@ComponentScan处理时就将扫描出的Bean注册到容器中了,@Import和@Bean是解析出后先存起来,在loadBeanDefinitionsForConfigurationClass才会将Bean注册到容器

未完待续......​​​​

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容