AbstractBeanDefinitionReader:
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取资源加载器,该资源加载器事实上是ClassPathXmlApplicationContext对象,从哪里得知呢?
ResourceLoader resourceLoader = getResourceLoader(); //代码1
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
//由于ClassPathXmlApplicationContext实现ResourcePatternResolver,将执行以下分支
if (resourceLoader instanceof ResourcePatternResolver) {
try {
//将字符串类型的配置文件转换为Spring能识别的Resource对象资源
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);//代码2
//进入重载的loadBeanDefinitions(Resource..)方法
//最终调用由XmlBeanDefinitionReader实现的loadBeanDefinitions(Resource resource)方法
//主线
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
...
return loadCount;
}
catch (IOException ex) {
...
}
}
else {
//仅可以从绝对路径加载单独的resource
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
...
return loadCount;
}
}
代码1的调用细节如下:
@Nullable
private ResourceLoader resourceLoader;
@Override
@Nullable
public ResourceLoader getResourceLoader() {
return this.resourceLoader;
}
成员变量resourceLoader分别有以下的赋值时机:
构造器初始化:
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// Determine ResourceLoader to use.
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
set方法:
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
此时我们回顾一下IoC的时候,是如何创建XmlBeanDefinitionReader对象的,以下代码回顾一下:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建一个Xml的BeanDefinition的读取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //代码1
//为BeanDefinition读取器配置当前上下文的资源加载环境
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this); //代码2
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//允许子类提供BeanDefinition的自定义初始化功能
initBeanDefinitionReader(beanDefinitionReader);
//执行事实上的加载
loadBeanDefinitions(beanDefinitionReader);
}
上述代码1和代码2其实都对resourceLoader进行了赋值操作,但是代码2在后面,因此最终resourceLoader为beanDefinitionReader.setResourceLoader(this)赋予的this值,此时的this的值为ClassPathXmlApplicationContext对象。