对配置类的BeanDefinition进行解析
// org.springframework.context.annotation.ConfigurationClassPostProcessor public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // 候选配置类集合 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); // 获取所有的BeanDefinition的name数组 String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 如果BeanDefinition中有这个属性存在,说明作为一个配置类已经被处理过了 if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 检查是否为一个配置类 // 查看是否具有@Configuration注解 // 这里不会仅仅看BeanDefinition所代表的类直接标注的注解,而是会递归查找其注解的注解是否有为 // @Configuration,只要找到了那么当前的类就是一个配置类 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // 找不到就结束 if (configCandidates.isEmpty()) { return; } // 对使用了@Order的进行排序 自然排序也就是升序 // 注意不是@Ordered configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // 如果有自定义Bean Name生成器,就使用自定义的 SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } // 如果还没有初始化Environment对象,初始化一个 if (this.environment == null) { this.environment = new StandardEnvironment(); } // 解析每一个被@Configuratin标注的注解类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // 构造一个BeanDefinitionReader if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 加载配置类中的@Bean,生成BeanDefinition this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); // 下面这段主要是考虑到@Import进来的或者@ImportSource或者@Bean等方式注入进来的会有配置类 if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); //把 ImportRegistry注册成一个Bean,以便支持 继承ImportAware 有注解类@Configuration的配置类 if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } }这个方法执行完后,所有的配置类都会被进行处理,并且在此过程中,BeanDefinition的总量有可能会增加,有新的BeanDefinition在解析过程新增进来。
这些BeanDefinition的来源就是存在于配置类上的其他注解
ConfigurationClassParserSpringBoot是如何使用一个@SpringBootApplication注解,完成了那么多的事情?