SpringBoot启动之上下文刷新(二)

上下文刷新阶段主要做什么事呢?

注册beanDefinition。

beanDefinition来自哪里?

  • 引用的spring-boot-starter jar包

  • 用户业务代码中的Component类包括Configuration、Service、Controller等等

了解了主要目标后,我们来分析源码。

1
2
3
4
5
6
7
8
9
10
//SpringApplication
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
...
}
}

跟进:

1
2
3
4
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}

调用到抽象上下文AbstractApplicationContext中的refresh方法,跟进去:

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
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新
prepareRefresh();
// 获取容器
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 容器做刷新前准备
prepareBeanFactory(beanFactory);
try {
// 执行上下文的beanFactory后置处理器方法,这是一个钩子方法,子类中实现
postProcessBeanFactory(beanFactory);
// 执行所有的beanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册bean后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化事件广播
initApplicationEventMulticaster();
// 供之类实现的,初始化特殊的Bean
onRefresh();
// 注册监听器
registerListeners();
// 实例化所有的(non-lazy-init)单例Bean
finishBeanFactoryInitialization(beanFactory);
// 发布刷新完毕事件
finishRefresh();
}
...
}

我们的关注点,beanDefinition的注册,在invokeBeanFactoryPostProcessors方法中,跟进:

1
2
3
4
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
...
}

继续跟,这个方法的源码非常长,但是逻辑很清晰,首先分析一下入参:

  • beanFactory 就是我么要刷新的容器
  • beanFactoryPostProcessors 到目前为止上下文中注册的beanFactory后处理器,里面的东西我们在此处不关心。

看这段代码前我们要先明确目标,我们要分析的是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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, 
List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 创建了一个HashSet存放已经执行完的后处理器的beanName
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
// 强转得到注册器
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 创建列表存放常规的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//创建列表存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 下面一个for循环执行的是参数传入的后处理器,不关心,直接跳过
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}

// 创建一个列表
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 关键点来了,从容器中获取BeanDefinitionRegistryPostProcessor
// 到目前为止还没有进行过注册,所有的后处理器都是上下文传过来的,容器中怎么会有后处理器呢?
// 答案就是上篇文章提到的root bean,spring boot启动的是会注册的内部启动类
// 其中就有一个bean是BeanDefinitionRegistry后处理器,那就是ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 主角被放入了currentRegistryProcessors列表中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//调用主角的方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}

上一篇文章中,讲到将主类注册到容器中时,容器中已经有了5个root bean:

其中的第一个名为org.springframework.context.annotation.internalConfigurationAnnotationProcessor的bean,它的类型是ConfigurationClassPostProcessor

首先调用到的是ConfigurationClassPostProcessor的此方法:

1
2
3
4
5
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
...
processConfigBeanDefinitions(registry);
}
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
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取已注册的beanName,此处获取到 5+1 组合 即5个rootbean 和 1个主类
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
...
// 此处检查该类是否为配置类,是否有@Configuration注解
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//将主类bd包装成BeanDefinitionHolder添加到候选名单
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
...
// 配置类解析器
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);

// 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());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);

candidates.clear();
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());
...
}

4.4 扩展点

4.4.1 ApplicationContextInitializer

只定义了一个方法:

1
2
3
4
5
6
7
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
/**
* 在refersh阶段执行
* 可以修改当前applicationContext的属性,例如扩展各种后置处理器
*/
void initialize(C applicationContext);
}

DelegatingApplicationContextInitializer 执行环境属性“context.initializer.classes”中指定的初始化程序,SpringBoot应用程序通过这种方式给用户提供了实现自定义Initializer的机会

ContextIdApplicationContextInitializer 从Environment中获取“spring.application.name”属性生成ContextId对象,将id 设置到上下文中,并在容器里注册ContextId单例对象

ConfigurationWarningsApplicationContextInitializer 在上下文中添加一个BeanFactory后处理器,用来warning因配置错误导致的异常

RSocketPortInfoApplicationContextInitializer 在上下文中增加一个监听器,用于监听RSocketServerInitializedEvent事件,该事件在contextRefresh完成且RSocketServer准备就绪时发布

4.4.2 BeanFactoryPostProcessor

只定义了一个方法

在IoC初始化之后执行,用于对已注册的BeanDefinition执行一些自定义操作

1
2
3
4
5
6
7
8
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* 在所有的ApplicationContextInitializer执行完之后,所有的beanDefinition都已加载,但还没有实例化之前执行
* 可以对该beanFactory进行任何可执行的操作(具体操作要看具体的beanFactory提供哪些操作)
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
4.4.3 BeanDefinitionRegistryPostProcesser

自身只定义了一个方法,当然也继承了父接口的方法,在refresh阶段BeanFactoryPostProcessor之前执行

用于在IoC初始化阶段,对IoC的初始化进行一些自定义操作

1
2
3
4
5
6
7
8
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

/**
* 在ApplicationContextInitializer的标准初始化之后修改它的内部bean定义注册表。所有的beanDefinition都已加载,但还没有实例化任何bean。
* 允许在下一个后处理阶段开始之前添加更多的bean定义
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

spring boot 内置的ConfigurationClassPostProcessor,是比较重要的后置处理器,用于在refresh阶段进行BeanDefinition的扫描和注册

5、ApplicationContext - DI 阶段

5.1 BeanPostProcesser

在容器实例化bean之后可以使用BeanPostProcesser对bean对象执行一些操作

因此可以猜测:应该是属于DI阶段的后处理器

参考资料:

springboot启动流程(目录)

context.refresh