Hexo

点滴积累 豁达处之

0%

ioc--扫描bean定义流程

这里分析bean定义是如何加载到容器里面的

加载步骤图

加载步骤如图显示:

Spring_beanDefinition01

加载源码分析

I0 refresh

org.springframework.context.support.AbstractApplicationContext#refresh 加载入口

1
2
3
4
5
public AnnotationConfigApplicationContext(Class... annotatedClasses) {
this();
this.register(annotatedClasses);
this.refresh();
}

I1 invokeBeanFactoryPostProcessors

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

执行BeanFactory后置处理(实例化bean工厂的后置处理器)

1
2
3
4
5
6
7
8
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

}

I1.1 processConfigBeanDefinitions

在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors 方法内部,

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

扫描、解析、注册所有配置类的Bean定义

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//1.初始化BeanDefinitionHolder集合
List<BeanDefinitionHolder> configCandidates = new ArrayList();
//2.所有已经注册的bean
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
//3.遍历已注册的bean数组
for(int var6 = 0; var6 < var5; ++var6) {
//bean名称
String beanName = var4[var6];
//得到BeanDefinition实例
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//判断:full configuration 和 lite configuration
//参照https://www.cnblogs.com/mufeng07/p/12163442.html
if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
//带有@Configuration注解的bean,beanDef的属性设置为full,beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "full");
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//带有@Configuration注解的bean添加到集合中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
} else if (this.logger.isDebugEnabled()) {
//两种都不满足,配置类已经被处理了
this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//集合非空
if (!configCandidates.isEmpty()) {
// 多个Java配置类,按@Ordered注解排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
//检测通过封闭的应用程序上下文提供的任何自定义bean名称生成策略
//暂时不理解
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
//web应用为StandardServletEnvironment
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//初始化一个ConfigurationClassParser解析器,可以解析@Congiguration配置类
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//List转成Set
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
//初始化一个已经解析的HashSet
HashSet alreadyParsed = new HashSet(configCandidates.size());
//循环解析,直到candidates为空
do {
//核心:解析
parser.parse(candidates);
//主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
//if (this.getMetadata().isAnnotated(Configuration.class.getName()) && this.getMetadata().isFinal())
parser.validate();
//排除已处理过的配置类
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
//读取模型并根据其内容创建bean定义
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
//2.加载bean定义信息,主要实现将@Configuration @Import @ImportResource @ImportRegistrar注册为bean
this.reader.loadBeanDefinitions(configClasses);
//将configClasses加入到已解析alreadyParsed中
alreadyParsed.addAll(configClasses);
//清空已处理的配置类
candidates.clear();
//再次获取容器中bean定义数量 如果大于 之前获取的bean定义数量,则说明有新的bean注册到容器中,需要再次解析
///getBeanDefinitionCount()取得是registry.beanDefinitionMap.size()
if (registry.getBeanDefinitionCount() > candidateNames.length) {
//容器中新的所有已注册的bean(包括老的)
String[] newCandidateNames = registry.getBeanDefinitionNames();
//容器中老的已注册的bean(已经解析了)
Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
//用来存储已经解析的类
Set<String> alreadyParsedClasses = new HashSet();
Iterator var12 = alreadyParsed.iterator();
//循环遍历把已解析的类放到alreadyParsedClasses中
while(var12.hasNext()) {
ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}

String[] var23 = newCandidateNames;
int var24 = newCandidateNames.length;
//循环遍历新的所有已注册的bean,排除老的已解析的,再过滤是否是配置类带有@Configuration,并且没有解析过,添加到candidates中,
//下一次可以再处理解析
for(int var14 = 0; var14 < var24; ++var14) {
String candidateName = var23[var14];
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));
}
}
}
...
}
}
}

i1.1.1 parse

org.springframework.context.annotation.ConfigurationClassParser#parse

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
public void parse(Set<BeanDefinitionHolder> configCandidates) {

// 实例化deferredImportSelectors
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();

// 遍历配置类,得到BeanDefinition,根据bd类型不同,调用不用的parse方法解析
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {

//debug的时候是自己写的启动类走的这个if
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}

// 处理deferredImportSelectors
processDeferredImportSelectors();
}

做了三件事:

1
2
3
1.实例化deferredImportSelectors
2.遍历配置类,得到BeanDefinition,根据bd类型不同,调用不同的parse方法解析
3.处理deferredImportSelectors

这里的parse方法再往下调用会调到ConfigurationClassParser类的processConfigurationClass方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void parse(Set<BeanDefinitionHolder> configCandidates) {
...
while(var2.hasNext()) {
...
try {
if (bd instanceof AnnotatedBeanDefinition) {
## 转到ConfigurationClassParser类的processConfigurationClass
this.parse(...);
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
this.parse(...);
} else {
this.parse(...);
}
.......

I1.1.1.1 processConfigurationClass

org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass

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
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {

// 是否跳过
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}

// 处理Imported
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext(); ) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}

// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);

// 递归解析
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);

// 添加到ConfigurationClassParser的configurationClasses中
this.configurationClasses.put(configClass, configClass);
}

做了四件事:

1
2
3
4
5
6
7
8
1.shouldSkip 方法判断是否跳过:
没有被@Conditional注解所修饰,返回false
如果参数中沒有设置条件注解的生效阶段,是配置类的话直接使用PARSE_CONFIGURATION阶段,递归调用shouldSkip,
否则使用REGISTER_BEAN阶段,递归调用shouldSkip 。获取配置类的条件注解得到条件数据,并添加到集合中
遍历conditions,进行判断,如果阶段不满足条件的话,返回true并跳过这个bean的解析
2.判断ConfigurationClassParser的configurationClasses中是否已有该配置类,判断是否需要处理imported
3.递归解析
4.添加到ConfigurationClassParser的configurationClasses中

doProcessConfigurationClass

org.springframework.context.annotation.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
91
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
// 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.warn("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 necessary

//遍历扫描到的配置类进行解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}

// Process any @Import annotations
// 处理@Import注解

processImports(configClass, sourceClass, getImports(sourceClass), true);

// Process any @ImportResource annotations.
// 处理@ImportResource 注解

if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
String[] resources = importResource.getStringArray("locations");

// 遍历配置的locations,加入到configClass 中的ImportedResource
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注释的方法,添加到configClass
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

// Process default methods on interfaces

// 处理接口定义的方法
processInterfaces(configClass, sourceClass);

// Process superclass, if any

// 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}

// No superclass -> processing is complete
return null;
}

做了八件事:

1
2
3
4
5
6
7
8
1.处理内部类
2.处理@PropertySource注解
3.处理@ComponentScan注解
4.处理@Import注解
5.处理@ImportResource注解
6.处理@Bean修饰的方法
7.处理接口定义的方法
8.处理父类