Spring源码讲解之 ClassPathXmlApplicationContext初始化过程

今天是2021年7月31日,2021年7月份的最后一天。我决定从今天起和大家一起学习springframework源码,由于工作日比较忙,所以,只能周末更新文章,望大家能够理解。
第一次自己写有关源码学习的文章,有什么不妥的地方希望大家提出宝贵意见,我会在后续文章中进行调整。
好了,废话不多说我们先从 ClassPathXmlApplicationContext 学起。
ClassPathXmlApplicationContext 是 ApplicationContext 的一个基类。通过读取类路径下的 xml bean 定义文件进行 bean 工厂创建并管理 bean 对象。

熟悉的程序

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	<bean name="user" class="spring.beans.User"></bean>
</beans>

ClassPathXmlApplicationContext构造函数

ClassPathXmlApplicationContext构造函数主要进行两件事

  1. 加载指定的配置文件
  2. 刷新上下文环境(即初始化bean工厂)
public ClassPathXmlApplicationContext(
	String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
	throws BeansException {
	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

super(parent)完成的事

  1. 初始化 org.springframework.context.support.AbstractApplicationContext.AbstractApplicationContext()
public AbstractApplicationContext() {
	this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
	return new PathMatchingResourcePatternResolver(this);
}
  1. 设置 parent org.springframework.context.support.AbstractApplicationContext.setParent(ApplicationContext)
public void setParent(@Nullable ApplicationContext parent) {
	this.parent = parent;
	if (parent != null) {
		Environment parentEnvironment = parent.getEnvironment();
		if (parentEnvironment instanceof ConfigurableEnvironment) {
			getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
		}
	}
}

setConfigLocations(configLocations) 是将配置文件赋值给 this.configLocations org.springframework.context.support.AbstractRefreshableConfigApplicationContext.setConfigLocations(String…)

public void setConfigLocations(@Nullable String... locations) {
	if (locations != null) {
		Assert.noNullElements(locations, "Config locations must not be null");
		this.configLocations = new String[locations.length];
		for (int i = 0; i < locations.length; i++) {
			this.configLocations[i] = resolvePath(locations[i]).trim();
		}
	}
	else {
		this.configLocations = null;
	}
}

refresh() 加载和刷新 bean 配置并将其加载到系统中org.springframework.context.support.AbstractApplicationContext.refresh()

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// org.springframework.context.support.AbstractApplicationContext.prepareRefresh()
		// 刷新 context 上下文前的准备:
		// 1、设置启动时间
		// 2、设置 context 状态
		// 3、初始化系统配置
		// 4、验证系统配置是否完整
		// 5、注册 ApplicationListeners
		// 6、初始化 ApplicationEvents 集合
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		// org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory()
		// 刷新 bean 工厂并将其实例返回
		// 如果 bean 工厂已创建则现将其关闭,再初始化一个新的 bean 工厂实例
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		// org.springframework.context.support.AbstractApplicationContext.prepareBeanFactory(ConfigurableListableBeanFactory)
		// 配置 bean 工厂实例
		// 1、设置 bean 工厂类加载器
		// 2、设置 bean 创建后的处理类
		// *3、注册特殊依赖项*
		// 4、注册 environment bean
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			// org.springframework.context.support.AbstractApplicationContext.postProcessBeanFactory(ConfigurableListableBeanFactory)
			// 设置 bean 工厂自定义扩展类,可以更改 bean 定义信息。默认为空实现
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			// org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)
			// 调用 bean 工厂自定义扩展处理
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			// org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(ConfigurableListableBeanFactory)
			// 注册 bean 实例自定义扩展
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			// org.springframework.context.support.AbstractApplicationContext.initMessageSource()
			// 初始化 MessageSource
			initMessageSource();

			// Initialize event multicaster for this context.
			// org.springframework.context.support.AbstractApplicationContext.initApplicationEventMulticaster()
			// 初始化 ApplicationEvent 管理器
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			// org.springframework.context.support.AbstractApplicationContext.onRefresh()
			// 初始化特定的刷新处理
			onRefresh();

			// Check for listener beans and register them.
			// org.springframework.context.support.AbstractApplicationContext.registerListeners()
			// 注册listener
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			// org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory)
			// 结束 bean 工厂初始化
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			// org.springframework.context.support.AbstractApplicationContext.finishRefresh()
			// 结束刷新操作
			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.
			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...
			resetCommonCaches();
		}
	}
}

以上内容是 new ClassPathXmlApplicationContext(“applicationContext.xml”) 所做的事情,由于时间问题,只是大概介绍了各个方法的作用,后面我会进行展开讲解,例如:XML 配置是如何被读取并转换成 bean 定义,bean工厂是如何初始化的等等一系列问题。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值