-
遍历ioc中已注册的bd,获取候选配置类
- @Configuration,设置为full类型配置类
- @Bean、@Component、@ComponentScan、 @Import、@ImportResource,设置为lite类型配置
- 解析配置类的@Order,设置BeanDefinition的order属性值
-
对候选配置类按@Order排序
-
准备BeanNameGenerator和Environment
-
初始化parser=ConfigurationClassParser
主要是初始化ComponentScanAnnotationParser和ConditionEvaluator -
主配置类包装成ConfigurationClass,利用parser开始解析
不断从主配置类下钻,类似多叉树深度遍历。遍历到叶子节点后加入parser的configurationClasses集合中- 利用ConditionEvaluator判断@Conditional是否满足,不满足结束(条件判断阶段为PARSE_CONFIGURATION阶段)
- 循环解析,因为注解可能在父类上
-
有内部类,递归第5步
-
@PropertySource
-
利用ComponentScanAnnotationParser解析@ComponentScan
- 利用ConditionEvaluator判断@Conditional是否满足,不满足结束(条件判断阶段为REGISTER_BEAN阶段)
- 初始化scanner=ClassPathBeanDefinitionScanner,默认添加2个includeFilter(@Component、@Configuration、@Controller、@Named、@Service、@Repository注解)
- 根据@Component的属性设置scanner,默认添加1个execludeFilter(排除自己)
- 获取扫描包路径,没有指定的话使用配置类的包路径,然后利用scanner扫描(ASM技术)
a. 先使用execludeFilters、includeFilters、@Condition过滤得到候选bd。
b. 再过滤候选bd是否非抽象外部类、抽象类(抽象类必须要有@Lookup修饰的方法)
c. 去重并注册bd。因为bd可能在处理其他@ComponentScan时被扫描过。没重复的bd直接注册到ioc容器中。 - 检查扫描出的bd还需要递归解析,因为可能上面还有full或lite类型的注解,根据bd中的类名封装成配置类,递归第5步
-
@Import
- 导入普通类
把它当成配置类,递归第5步 - 导入ImportBeanDefinitionRegistrar
实例化registrar、执行Aware接口方法、把registrar加入配置类的importBeanDefinitionRegistrars中,后续会用到 - 导入ImportSelector
实例化selector、执行Aware接口方法、判断是否DeferredImportSelector。
如果不是DeferredImportSelector,执行selector.selectImports()得到导入的类名集合,再递归@Import步骤。如果是DeferredImportSelector, 把selector加入parser的deferredImportSelectors中,后续会用到
- 导入普通类
-
@ImportResource
获取属性指定的reader,保存在配置类的importedResources中,后续会用到 -
@Bean
将@Bean方法转化为BeanMethod对象,保存在配置类的beanMethods中,后续会用到 -
处理接口默认方法上的@Bean,类似于@Bean处理
-
- 把配置类加入parser的configurationClasses中,底层是个LinkedHashSet,保证了配置类解析顺序
-
遍历parser的deferredImportSelectors,执行selectImports()
这是留给其它框架注册bd的1个入口,比如springboot的自动配置 -
遍历parser的configurationClasses,进行bd验证
a. @Configuration的配置类不能是final
b. @Bean修饰的方法必须可以重写以支持CGLIB -
初始化reader=ConfigurationClassBeanDefinitionReader
-
遍历parser的configurationClasses,利用reader注册剩余的bd
- 对已扫描注册的bd再一次进行@Conditional判断,如果不满足从 BeanDefinitionRegistry移除。springboot的@ConditionalOnBean就在这儿判断
- 注册内部类和@Import的普通类
- 注册@Bean
a. 初始化bd=ConfigurationClassBeanDefinition。
b. 非static方法,设置bd的factoryBeanName和factoryMethodName。
c. static方法,设置bd的beanClass和factoryMethodName。
d. 设置autowire属性,AUTOWIRE_BY_TYPE、AUTOWIRE_BY_NAME。
e. 解析@Scope,如果设置了proxyMode则创建1个代理bd。
f. 解析@Lazy、@Primary、@Role、@DependsOn、@Description - 注册@ImportResource导入的
- 注册ImportBeanDefinitionRegistrar导入的
遍历配置类的importBeanDefinitionRegistrars,执行registerBeanDefinitions方法去注册bd
判断是否bd是否有@Configuration注解,有就生成1个代理类并setBeanClass。
另外,添加1个处理器ImportAwareBeanPostProcessor



