Spring 源码之容器加载

加载文件方式

xml 配置文件

类路径获取配置文件

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring.xml");

文件系统路径获取配置文件

ApplicationContext applicationContext = new FileSystemXmlApplicationContext("/home/usr/learn-spring-framework5.2/spring-demo/src/main/resources/spring.xml");

Java 配置类

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringDemoConfig.class);

Spring 核心加载方法

AbstractApplicationContext#refresh()方法是 Spring 容器启动过程中的核心方法

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
/**
* 加载或刷新配置的持久化表示,可能是XML文件、属性文件或关系数据库。
* 由于这是一个启动方法,如果它调用失败,它应该销毁已创建的单例,以避免悬空资源。换句话说,在调用该方法之后,要么全部实例化,要么都不实例化。
* @throws BeansException
* @throws IllegalStateException
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
/*
* 使用对象锁 startUpShutdownMonitor 进行同步控制:
* 1、避免了多线程同时刷新 spring 配置,只对不能并发的代码块进行加锁, 提高了整体代码运行的效率;
* 2、refresh() 方法和 close() 方法都使用了 startUpShutdownMonitor 对象锁加锁,
* 这就保证了在调用 refresh() 方法的时候无法调用 close() 方法,避免了冲突;
**/
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 容器刷新前的准备工作
/*
* 1. 设置容器的启动时间
* 2. 设置容器开启和关闭标志位
* 3. 获取 Environment 对象, 并加载当前系统的属性到 Environment 对象中
* 4. 准备监听器和事件的集合对象, 默认为空集合
*/
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 创建容器对象:DefaultListableBeanFactory
// 解析xml配置文件的属性值封装到BeanDefinition对象中, 并注册到当前工厂中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// beanFactory的准备工作,对各种属性进行填充(为容器注册必要的系统级别的Bean)
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 允许容器的子类去注册 postProcessor, 钩子方法
// 子类覆盖方法做额外的处理, 可参考 web 中的代码
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 调用容器中的各种 beanFactory 的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
// 向容器注册 bean 的后置处理器,这里只是注册功能,真正调用的是 getBean 方法
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
// 为上下文初始化message源,即不同语言的消息体 (国际化处理)
initMessageSource();

// Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 在单例 Bean 初始化之前预留子类初始化其他特殊 Bean 的口子, 钩子方法
onRefresh();

// Check for listener beans and register them.
// 在所有注册的 bean 中查找 listener bean, 注册到消息广播器中
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非懒加载)单例
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,
// 同时发出 ContextRefreshEvent 事件通知别人
finishRefresh();
}

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

// Destroy already created singletons to avoid dangling resources.
// 销毁已经创建的Bean
destroyBeans();

// Reset 'active' flag.
// 重置容器激活标签
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
// 重置 Spring 内核中的公用缓存
resetCommonCaches();
}
}
}