配置类bean的由来
在ConfigurationClassPostProcessor中的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法中,有如下代码:
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
这两句的作用是遍历configClasses,如果importedBy属性不为空,会将该类添加到IoC容器的beanDefinitionMap和beanDefinitionNames变量中,然后将上图中下面三个属性涉及到的bean添加到bdm和bdn。configClasses是parser的configurationClasses(key-value键值对)的键集合,在扫描的时候,会将每一次解析所对应的bean添加到configurationClasses变量中,然而发现不止这么多,因而产生了疑问:那些多余的configurationClasses如何而来?
往上追溯进入parser.parse(candidates),发现是this.deferredImportSelectorHandler.process()这一句起的作用。
// deferred是延迟的意思
ConfigurationClassParser->DeferredImportSelectorHandler->process():
handler.processGroupImports();
ConfigurationClassParser->DeferredImportSelectorGroupingHandler->processGroupImports():
grouping.getImports()
ConfigurationClassParser->DeferredImportSelectorGrouping->getImports():
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
AutoConfigurationImportSelector->AutoConfigurationGroup->process():
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(),
annotationMetadata);
AutoConfigurationImportSelector->getAutoConfigurationEntry():
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
AutoConfigurationImportSelector->getCandidateConfigurations():
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
SpringFactoriesLoader->loadFactoryNames():
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
在SpringFactoriesLoader类中,loadSpringFactories(classLoader)返回的是key-value的键值对,factoryClassName的值为org.springframework.boot.autoconfigure.EnableAutoConfiguration,在这边初步拿到这些bean集合(假设为下图中的125个)。然后遍历,如果有真正的类,则使用Class.forName加载,加载成功返回true,否则返回false,最终剔除掉为false的bean。
附录:SpringFactoriesLoader的loadFactoryNames方法:
假设classLoader不为空,则依次读取jar包下的META-INF/spring.factories文件,以下图为例:
result是一个map集合,与之一一对应,在读取不同的
spring.factories文件时,如果存在相同的key,则合并。
根据传过来的factoryClass得到它的全限定名,如注解EnableAutoConfiguration的全限定名为org.springframework.boot.autoconfigure.EnableAutoConfiguration。
当key为它时,返回图一中的125个
总结
万始之源:启动类下的@EnableAutoConfiguration注解
- 找到配置类bean
- jar包没有引入则剔除(使用
Class.forName实现) - 解析配置类,加入到
configurationClasses - 遍历
configurationClasses,将发现的bean添加到容器的到bdm和bdn变量中