此处处理的是在配置类中具有@Bean注解的方法
// ①
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
// ②
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// ④
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
for (SourceClass ifc : sourceClass.getInterfaces()) {
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (MethodMetadata methodMetadata : beanMethods) {
if (!methodMetadata.isAbstract()) {
// A default method or other concrete method on a Java 8+ interface...
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
processInterfaces(configClass, ifc);
}
}
// ⑤
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
① - 获取所有具有@Bean注解的方法
② - 将获取到的方法包装为BeanMethod对象(表示一个具有@Bean注解的@Configuration类的方法)保存到当前配置类的beanMethods属性中
④ - 处理接口中具有@Bean注解的方法
⑤ - 处理父类中具有@Bean注解的方法
取出@Configuration
直接从Parser中取出之前解析时缓存的配置类,因为这段代码在do-while循环中,因此首先移除已处理的。
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
构建BeanDefinitionReader
若Reader为空,则创建,用于读取配置中的BeanDefinition
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
@Configuration读取BeanDefinition
前面对各种注解的的解析最终并没有处理解析的结果,而是将其放在了ConfigurationClass对象的属性当中存储,在这里将通过Reader来处理这
些不同来源的BeanDefinition。
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// ①
for (ConfigurationClass configClass : configurationModel) {
// ②
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
① - 遍历所有的@Configuration
② - 从@Configuration读取BeanDefinition
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;
}
// ②
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// ③
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// ④
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// ⑤
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
① - 是否需要跳过
② - 当前配置类本身是否通过@Import导入,若有则将自身注册为BeanDefinition
③ - 当前配置类中是否有@Bean注解修饰的方法,若有则处理
④ - 加载从@ImportResource导入的XML文件中定义的Bean
⑤ - 加载从@Import导入的BeanDefinition
合并已处理的BeanDefinition
// ①
String[] candidateNames = registry.getBeanDefinitionNames();
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;
}