这篇以及后面的几篇blog,都将讨论ApplicationContext初始化过程,其大致流程就需要完成与BeanDefinition相关的三件事1、Resource定位;2、载入;3、注册。
下面主要以FileSystemXmlApplicationContext类为例
1、 定位资源:
ApplicationContext context = new FileSystemXmlApplicationContext(xmlPath);//用户代码
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
调用了构造函数FileSystemXmlApplicationContext(String[] configLocations, booleanrefresh, ApplicationContext parent)
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
在这篇文章中主要讲这个构造函数中前两个方法:super(parent); 调用父类的构造方法;调用父类AbstractRefreshableConfigApplicationContext中的setConfigLocations(configLocations);方法。
1、 super(parent); 调用父类的构造方法主要是设置资源加载器并为容器根据父类的位置设置运行环境。通过追踪FileSystemXmlApplicationContext的继承关系,发现在其父类的父类AbstractApplicationContext中做了IOC容器初始化相关的工作,下面看一下具体的源码。
图一:super(parent); 调用关系
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
static {
//避免应用程序在Weblogic8.1关闭时出现类加载异常加载问题,加载IoC容
//器关闭事件(ContextClosedEvent)类
ContextClosedEvent.class.getName();
}
//创建一个新的没有父类的AbstractApplicationContext
//设置资源加载器
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
//获取一个Spring Source的加载器用于读入Spring Bean定义资源文件
protected ResourcePatternResolver getResourcePatternResolver() {
// AbstractApplicationContext继承DefaultResourceLoader,也是一个Spring资源加载器
// 也实现了getResource(String location)方法用于载入资源
return new PathMatchingResourcePatternResolver(this);
}
//根据父类创建一个新的ApplicationContext
public AbstractApplicationContext(ApplicationContext parent) {
this();
setParent(parent);
}
// 创建一个上下文环境 如果父类环境非空且是子类ConfigurableEnvironment,
// 就是设置当前应用程序的资源环境是parentEnvironment
// Spring资源加载器,其方法用于载入资源
@Override
public void setParent(ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
}
2、 setConfigLocations(configLocations);方法则是为为此应用程序上下文设置配置位置。
//AbstractRefreshableConfigApplicationContext 类中
//为此应用程序上下文设置配置位置。
//如果没有设置,则实现可以使用默认值。
public void setConfigLocations(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;
}
}