源码解析(基于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注册到容器
未完待续......