spring 源码分析--IOC容器初始化四
的抽象父类-AbstractBeanDefinitionReader中:
//这里得到当前定义的ResourceLoader,默认的我们使用DefaultResourceLoader
ResourceLoader resourceLoader =getResourceLoader();
//如果没有找到我们需要的ResourceLoader,直接抛出异常
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
}
/**
* 由getResourceLoader()函数可知resourceLoader为
* PathMatchingResourcePatternResolver类型,而
* PathMatchingResourcePatternResolver继承ResourcePatternResolver
*这里处理我们在定义位置时使用的各种pattern,需要ResourcePatternResolver来完成
*/
if (resourceLoader instanceof ResourcePatternResolver) {
try {
/**
* 自此对资源文件的装载过程结束。下面是对文件的解析和初始化bean过程,下面的函数最终
* 会调用XmlBeanDefinitionReader类的loadBeanDefinitions(EncodedResource
* encodedResource)
*/
??? int loadCount = loadBeanDefinitions(resources);
??? if (actualResources != null) {
??? ??? for (int i = 0; i <resources.length; i++) {
?????? ??? actualResources.add(resources[i]);
??? ??? }
}
if (logger.isDebugEnabled()) {
??? }
??? return loadCount;
}catch (IOException ex) {
??? throw new BeanDefinitionStoreException(
?????? "Could not resolve beandefinition resource pattern [" + location+ "]", ex);
}
}else {
// Can only load single resources by absolute URL.
??? //这里通过ResourceLoader来完成位置定位
??? Resource resource = resourceLoader.getResource(location);
??? //这里已经把一个位置定义转化为Resource接口,可以供XmlBeanDefinitionReader来使用了
??? int loadCount = loadBeanDefinitions(resource);
??? if (actualResources != null) {
?????? actualResources.add(resource);
??? }
??? if (logger.isDebugEnabled()) {
??? }
??? return loadCount;
}
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
?????? super(registry);
Assert.notNull(registry,"BeanDefinitionRegistry must not benull");
this.registry = registry;
// Determine ResourceLoaderto use.
if (this.registry instanceof ResourceLoader) {
??? this.resourceLoader = (ResourceLoader) this.registry;
}else {
??? this.resourceLoader = new PathMatchingResourcePatternResolver();
public Resource[] getResources(String locationPattern) throws IOException {
??? Assert.notNull(locationPattern,"Locationpattern must not be null");
// 如果locationPattern是以字符串: “classpath*:”开始。
??? if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
if(getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
?????? //一个classpath资源。
??? ??? returnfindPathMatchingResources(locationPattern);
??? ?? }else {
?????? //多个classpath资源
?????? }
??? }else {
?????? // Only lookfor a pattern after a prefix here
?????? // (to not get fooled by apattern symbol in a strange prefix).
?????? int prefixEnd =locationPattern.indexOf(":") + 1;
?????????? //文件类型
?????? ??? return findPathMatchingResources(locationPattern);
?????? }else {
?????????? // a single resource with the given name
?????? }
??? }
}
?
public Resource getResource(String location) {
??? Assert.notNull(location,"Location must not be null");
??? //如果是类路径的方式,那需要使用ClassPathResource来得到bean文件的资源对象
??? if (location.startsWith(CLASSPATH_URL_PREFIX)) {
??? }else {
?????? try {
?????????? // Try to parse the location as a URL...
?????????? // 如果是URL方式,使用UrlResource作为bean文件的资源对象?
?????????? URL url = new URL(location);
?????????? return new UrlResource(url);
?????? }catch (MalformedURLException ex) {
??? ?????? //如果都不是,那我们只能委托给子类由子类来决定使用什么样的资源对象了?
?????????? // No URL -> resolve as resource path.
?????????? return getResourceByPath(location);
?????? }
??? }
protected Resource getResourceByPath(String path) {
?????? if (path != null && path.startsWith("/")) {
?????????? path = path.substring(1);
?????? }
?????? //这里使用文件系统资源对象来定义bean文件?
?????? return new FileSystemResource(path);
??? }
====================================================================
这样代码就回到了FileSystemXmlApplicationContext中来,他提供了FileSystemResource来完成从文件系统得到配置文件的资源定义。这样,就可以从文件系统路径上对IOC配置文件进行加载 - 当然我们可以按照这个逻辑从任何地方加载,在Spring中我们看到它提供的各种资源抽象,比如ClassPathResource, URLResource,FileSystemResource等来供我们使用。上面我们看到的是定位Resource的一个过程,而这只是加载过程的一 部分 - 我们回到AbstractBeanDefinitionReaderz中的loadDefinitions(resource)来看看得到代表bean文 件的资源定义以后的载入过程,默认的我们使用XmlBeanDefinitionReader返回
?