Spring-01-什么是context

Spring-04-什么是Bean的容器

先对BeanFactory有了了解,也就是说一个框架已经有了能力实现对Bean对象的管理,那么下一步是什么,肯定是围绕已有核心能力提供周边建设,context就是面向应用的一个,打包好的,开箱即用的一整套东西

从SpringBoot看的时候,用了AnnotationConfigApplicationContext

1 它有什么组件

1
2
3
4
5
6
7
8
9
10
public AnnotationConfigApplicationContext() {
// 会隐式调用到父类GenericApplicationContext 构造一个beanFactory的DefaultListableFactory对象出来
/**
* 为什么要构造下面这两个玩意 本质都是为了找到BeanDefinition 然后把BeanDefinition缓存到BeanFactory里面
* 将来给过来的信息可能是一个打了注解的类 也有可能是下包路径
* 下面两个各司其职
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
1
2
3
4
public GenericApplicationContext() {
// Spring的核心
this.beanFactory = new DefaultListableBeanFactory();
}

2 大名鼎鼎的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
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
@Override
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();

StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

// Prepare this context for refreshing.
// 1 准备context
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 2 从context中把BeanFactory对象拿出来 DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// 3 增强BeanFactory context给BeanFactory准备一些基础设施
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 4 context的一个扩展点 默认是空实现 预留的口子 想做一些增强操作的就重写这个方法
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
/**
* 5 让BeanFactoryPostProcessor修改BeanDefinition
* SpringBoot启动的时候只往BeanFactory里面缓存了一个启动类的BeanDefinition 在这个地方就要开始围绕这个启动类的BeanDefinition找到枝枝蔓蔓
* BeanFactoryPostProcessor作用时机是在Bean实例化之前 操作对象是BeanDefinition
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/**
* 6 BeanPostProcessor作用时机是Bean实例化过程中 操作对象是Bean对象 在实例创建过程中进行干预
* 为什么要先注册BeanPostProcessor呢 因为后面会真正创建Bean
*/
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
// 7 国际化
initMessageSource();

// Initialize event multicaster for this context.
// 8 构造事件发布器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 9 给具体的ApplicationContext扩展
onRefresh();

// Check for listener beans and register them.
// 10 注册ApplicationListener
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 11 真正创建Bean
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 12 所有主要的Bean都创建完成了 对context做一些最终的工作
finishRefresh();
}

catch (RuntimeException | Error ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Stop already started Lifecycle beans to avoid dangling resources.
if (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning()) {
try {
this.lifecycleProcessor.stop();
}
catch (Throwable ex2) {
logger.warn("Exception thrown from LifecycleProcessor on cancelled refresh", ex2);
}
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
contextRefresh.end();
}
}
finally {
this.startupShutdownThread = null;
this.startupShutdownLock.unlock();
}
}

我会把核心的步骤单独成一个篇章


Spring-01-什么是context
https://bannirui.github.io/2023/03/11/Spring/Spring-01-什么是context/
作者
dingrui
发布于
2023年3月11日
许可协议