Spring ConfigurationClassParser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- ConfigurationClassPostProcessor.processConfigBeanDefinitions()
- 1.获取 registry 中的 beanDefinitionNames
- 2.遍历beanDefinitionNames判断beanDefinition 是否是 @Configuration 配置类,若是则添加到 configCandidates 集合中
- 3.configCandidates根据Order排序
- 4.创建ConfigurationClassParser,配置类解析器
- 5.遍历configCandidates,调用parser.parse()进行配置类解析
- ConfigurationClassParser.parse()
- 1.遍历configCandidates,获取当前的beanDefinition
- 2.根据不同类型的beanDefinition,调用不同入参的parse()方法
- ConfigurationClassParser.processConfigurationClass()
- 1.是否需要跳过 @Conditional
- 2.循环递归调用doProcessConfigurationClass()方法,处理配置类和父类,直到没有父类时,方法返回null,结束循环
- ConfigurationClassParser.doProcessConfigurationClass()
- 1.判断是否含有 @Component 注解,首先递归处理任何成员(嵌套)类
- 2.若有PropertySources注解,循环处理 @PropertySource 注解
- 3.若有@ComponentScan注解,处理 @ComponentScan 注解
- 4.处理 @Import 注解
- 5.若有 @ImportResource 注解,处理 @ImportResource 注解
- 6.处理 @Bean 注解的方法
- 7.如果有父类,获取父类名,外层循环会继续调用该方法解析父类.没有父类返回null,结束循环
- 6.loadBeanDefinitions() 把前面解析出来的对象注册到容器中

ConfigurationClassParser.doProcessConfigurationClass()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/** 通过解析源类中的 注解、成员 和 方法,创建 ConfigurationClass
* Apply processing and build a complete {@link ConfigurationClass} by reading the
* annotations, members and methods from the source class. This method can be called
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, or {@code null} if none found or previously processed
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {

if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 含有 @Component 注解
// Recursively process any member (nested) classes first.首先递归处理任何成员(嵌套)类
processMemberClasses(configClass, sourceClass);
}

// Process any @PropertySource annotations. 处理 @PropertySource
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}

// Process any @ComponentScan annotations. 处理 @ComponentScan 注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { // 判断解析获取的 BeanDefinition 中 是否有配置类.也就是说只要有 @Configuration、@Component、@ComponentScan、@Import、@ImportResource 和 @Bean 中的其中一个注解
parse(bdCand.getBeanClassName(), holder.getBeanName()); // 如果有配置类,递归调用,解析该配置类
}
}
}
}

// Process any @Import annotations. 处理 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), true);

// Process any @ImportResource annotations. 处理 @ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}

// Process individual @Bean methods. 处理 @Bean 方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); // 检索 @Bean 方法
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); // 创建 BeanMethod,添加到 beanMethods
}

// Process default methods on interfaces
processInterfaces(configClass, sourceClass);

// Process superclass, if any. 如果有父类,则解析父类
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(); // 不返回null,外层循环调用
}
}

// No superclass -> processing is complete
return null; // 循环出口.没有父类,处理完成,返回null,外层结束循环
}