接 springIOC - ConfigurationClassPostProcessor - full / lite
代码块:
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
do { parser.parse(candidates); parser.validate(); //map.keyset Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } /** * 这里值得注意的是扫描出来的bean当中可能包含了特殊类 * 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理 * 但是并不是包含在configClasses当中 * configClasses当中主要包含的是importSelector * 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了 */ //将 bd 放到 map 中 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); //由于我们这里进行了扫描,把扫描出来的BeanDefinition注册给了factory //但是 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());
parse 解析完后, 就会调用 loadBeanDefinitions方法.
这方法会将 StartConfig.java 解析出来的一些 bd, 注册到spring容器中.
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
这个方法里面, 就会对配置文件中的 @Bean 进行注册,
然后会调用 前面解析到的 ImportBeanDefinitionRegistrar.registerBeanDefinitions 方法.
private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { this.registry.removeBeanDefinition(beanName); } this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); return; } // 注册 @Import 导入的普通 bean , 或者 ImportSelector 导入的普通bean if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } //@Bean 的注册 for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } //xml loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); //注册Registrar loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
这里需要特别注意一下 loadBeanDefinitionsForBeanMethod
他是对 @Bean 进行注册的, 有一段代码比较重要
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); //如果 method 是静态的 if (metadata.isStatic()) { // static @Bean method
// static时, 设置的是 BeanClassName 属性 beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(methodName); } else { //非static的 method, 设置了一个 FactoryBeanName 属性 // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
这里配置了构造函数自动注入模式
实例代码:
@Configuration public class AppConfig { @Bean public static A a(){ return new A(); } @Bean public B b(){ a(); return new B(); } }
这里对 A 和 B 都进行了解析, 转化成了 ConfigurationClassBeanDefinition
1.静态方法时, 设置的
BeanClassName = "xxx.xxx.xxx.AppConfig"
FactoryMethodName = "a"
创建的时候, 会来找 AppConfig的a()
2.非静态方法时, 设置的
FactoryBeanName = "xxx.xxx.xxx.AppConfig"
UniqueFactoryMethodName = "b"
创建 b 的时候, 会来这里找 b() 方法
BeanFactory后置处理器 - ConfigurationClassPostProcessor - this.reader.loadBeanDefinitions