入口
常使用的入口
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
}
我们看一下 ClassPathXmlApplicationContext
的构造函数:
ClassPathXmlApplicationContext.java
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
发现我们最终调用的构造函数是:
ClassPathXmlApplicationContext.java
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
this.refresh();
}
}
通过构造函数,我们可以分析出创建 ClassPathXmlApplicationContext
容器时,构造函数做了以下事情:
- 调用父容器的构造方法
super(parent)
,为容器设置好Bean 资源解析器; - 调用父类
AbstractRefreshableConfigApplicationContext
的setConfigLocations(configLocations)
方法,设置Bean 配置信息的定位路径; - 调用
refresh()
方法。
设置Bean 资源加载器
通过追踪 super(parent)
,发现 AbstractApplicationContext
最终的构造函数:
AbstractApplicationContext.java
public abstract class AbstractApplicationContext
extends DefaultResourceLoader
implements ConfigurableApplicationContext{
public AbstractApplicationContext() {
this.logger = LogFactory.getLog(this.getClass());
this.id = ObjectUtils.identityToString(this);
this.displayName = ObjectUtils.identityToString(this);
this.beanFactoryPostProcessors = new ArrayList();
this.active = new AtomicBoolean();
this.closed = new AtomicBoolean();
this.startupShutdownMonitor = new Object();
this.applicationListeners = new LinkedHashSet();
// 获取一个spring source 的资源解析器
this.resourcePatternResolver = this.getResourcePatternResolver();
}
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
this.setParent(parent);
}
// 获取一个spring source 的资源解析器用于读取Spring Bean 信息
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
}
调用 PathMatchingResourcePatternResolver
的构造函数来创建Spring 资源加载器:
PathMatchingResourcePatternResolver.java
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
// 设置Spring 资源加载器
this.resourceLoader = resourceLoader;
}
这里需要注意的是: AbstractApplicationContext
继承 DefaultResourceLoader
,因此也是一个资源加载器,所以能够作为参数。
Bean 配置信息的定位
在设置Bean 资源解析器之后,接下来 ClassPathXmlApplicationContext
通过调用父类 AbstractRefreshableConfigApplicationContext
的 setConfigLocations(configLocations)
方法,设置Bean 配置信息的定位路径.。该方法的源码如下:
AbstractRefreshableConfigApplicationContext.java
// 处理多个资源文件路径为一个字符串的情况
public void setConfigLocation(String location) {
// 按照",; \t\n",将多个资源文件路径进行分割,解析为数组形式
this.setConfigLocations(StringUtils.tokenizeToStringArray(location, ",; \t\n"));
}
// 解析Bean 定义资源文件的路径,处理多个文件字符串数组
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) {
// resolvePath 为将字符串解析为路径的方法
this.configLocations[i] = this.resolvePath(locations[i]).trim();
}
} else {
this.configLocations = null;
}
}
从以上两个方法我们可以看出:我们既可以使用一个字符串来配置多个Spring Bean 资源文件信息,也可以用字符串数组进行配置。多个资源文件路径之间是可以使用“,;\t\n”进行分割。