Spring启动扫描流程(伪代码)


//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())
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值