0%

源码分析之上下文构建

源码分析之上下文构建

先从最简单的上下文初始化来开始说起

1
ApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");

一个简单地创建ApplicationContext实例的方法,spring会做什么事呢?

1
2
3
4
5
6
7
8
9
10
11
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {

super(parent);
// 为上下文设置配置文件的位置
setConfigLocations(configLocations);
if (refresh) {
// 刷新上下文
refresh();
}
}

spring在初始化上下文的最重要的方法就是这个refresh()方法了

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
public void refresh() throws BeansException, IllegalStateException {
//容器重启同步监控锁,防止刷新进行到一半被重复执行
synchronized (this.startupShutdownMonitor) {
// 准备应用上下文,填充配置文件占位符,记录容器启动时间和启动状态
prepareRefresh();

// 刷新内部bean factory,即在子类中启动refreshBeanFactory()的地方,创建bean工厂,根据配置文件生成bean定义,完成配置文件定义到注册表登记bean的流程,此时对象还未被创建
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 准备bean工厂,配置类加载器,定制特殊bean,添加BeanPostProcessor可供回调
prepareBeanFactory(beanFactory);

try {
// 工厂加载完配置,初始化之前回调PostProcessBeanFactory,作为工厂扩展功能,子类想在bean定义加载完成后,开始初始化上下文之前做一些特殊逻辑
postProcessBeanFactory(beanFactory);

// 调用BeanFactory的后置处理器,这些后处理器是在Bean定义中向容器注册的
invokeBeanFactoryPostProcessors(beanFactory);

// bean扩展:postProcessBeforeInitialization和postProcessAfterInitialization,分别在Bean初始化之前和初始化之后得到执行
registerBeanPostProcessors(beanFactory);

//初始化MessageSource对象,国际化
initMessageSource();

// 初始化上下文中的事件机制
initApplicationEventMulticaster();

// 初始化其他的特殊Bean
onRefresh();

// 注册监听器,检查监听Bean并且将这些Bean向容器注册
registerListeners();

// 实例化工厂注册表里所有的(non-lazy-init)单例bean
finishBeanFactoryInitialization(beanFactory);

// 发布容器事件,结束refresh过程
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 为防止资源占用,如果出现异常销毁已经创建好的单例bean
destroyBeans();
// 重置active标志
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...
resetCommonCaches();
}
}
}

prepareRefresh方法

容器初始化之前的初始化工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}

// Initialize any placeholder property sources in the context environment.
// 初始化占位符
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
//校验配置文件
getEnvironment().validateRequiredProperties();

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

obtainFreshBeanFactory方法

创建BeanFactory

1
2
3
4
5
6
7
8
9
10
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 关闭原始的beanFactory,并创建新的BeanFactory
refreshBeanFactory();
//返回创建的新工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

重置BeanFactory,存在则销毁,不存在则创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected final void refreshBeanFactory() throws BeansException {
// 如果存在BeanFactory,则进行销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//设置容器是否允许对象覆盖,循环依赖
customizeBeanFactory(beanFactory);
// 读取xml配置文件,BeanDefinition
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}