//org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors#invokeBeanDefinitionRegistryPostProcessors(1)
//org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
//初步获取配置类(通过构造或register()方法注册),按优先级升序 Set<BeanDefinitionHolder> candidates
do{
ConfigurationClassParser parser = new ConfigurationClassParser(...);
// 遍历 candidates
parser.parse(candidates){
// 提取为BeanDefinition处理
for (BeanDefinitionHolder holder : configCandidates) {
processConfigurationClass(...){
// 把类的元信息和beanName封装为ConfigurationClass
// 1、不满足 @Conditional ,跳过
this.conditionEvaluator.shouldSkip(...);
// 2、递归向上查找配置类,遍历并按下述流程判断
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter){
// 3、@Component判断其内部类是否为配置类,如果是,processConfigurationClass 继续递归处理
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processConfigurationClass(...){}
}
// 4、@PropertySources 解析到 environment 对象中
// 。。。
// 5、@ComponentScan,通过includeFilter、excludeFilter(@Component @ManagedBean @Named)、@Conditional)过滤生成并注册BeanDefinition
// 如果扫描出了配置类,processConfigurationClass 继续递归处理
Set<BeanDefinitionHolder> scannedBeanDefinitions;
// 触发 doScan 扫描逻辑(通过 @Component 配置的value如果重复会抛异常)
scanner.doScan(StringUtils.toStringArray(basePackages));
processConfigurationClass(...){}
// 6、@Import 按照是否实现接口暂缓或立即处理
// @Import查找逻辑:递归
processImports(..., getImports(sourceClass), ...){
// 实现了 ImportSelector.class
// 1、是 DeferredImportSelector 类型,推迟处理
this.deferredImportSelectorHandler.handle(...) => (ConfigurationClassParser.)deferredImportSelectors.add(...)
// 2、非 DeferredImportSelector 类型,递归查找所有被注释了@Import的类,processImports 递归
processImports(...){}
// 实现了 ImportBeanDefinitionRegistrar.class
(ConfigurationClass.)importBeanDefinitionRegistrars.put(...)
// 非 ImportSelector & ImportBeanDefinitionRegistrar 类型,作为 @Configuration 处理
processConfigurationClass(...){}
}
// 7、@ImportResource 暂存至 ConfigurationClass.importedResources
(ConfigurationClass.)importedResources.put(...)
// 8、类中存在的@Bean注解方法缓存至 ConfigurationClass.beanMethods
// 9、如果类实现了接口且存在@Bean注解方法,缓存至 ConfigurationClass.beanMethods
(ConfigurationClass.)beanMethods.add(...)
// 10、如果还存在父类,继续while循环
sourceClass = sourceClass.getSuperClass();
}
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
}
// 处理DeferredImportSelector类型,升序排序处理
this.deferredImportSelectorHandler.process(){
processImports(...){}
}
}
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); // => 即this.configurationClasses
this.reader.loadBeanDefinitions(configClasses){
// 通过 @Import 被导入的,注册到Spring容器
registerBeanDefinitionForImportedConfigurationClass(configClass);
// 处理 ConfigurationClass.beanMethods,满足条件加入Spring容器(如果 @Component & @Bean 配置名称相同,@Bean 会覆盖 @Component 配置)
loadBeanDefinitionsForBeanMethod(beanMethod);
// 处理 ConfigurationClass.importedResources,满足条件加入Spring容器 ==> 通过 @ImportResource 引入的 *.xml 文件
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 处理 ConfigurationClass.importBeanDefinitionRegistrars,满足条件加入Spring容器
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
candidates.clear();
// 如果扫描并注册了新的BeanDefinition,判断是否为配置类,如果是,加入candidates,循环继续
candidates.add(...);
}while (!candidates.isEmpty())
Spring启动扫描流程(伪代码)
最新推荐文章于 2024-01-02 15:40:55 发布