BeanDefinition的Resource定位——2
1.FileSystemXmlApplicationContext的实现
1 public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { 2 3 /** 4 * Create a new FileSystemXmlApplicationContext for bean-style configuration. 5 * @see #setConfigLocation 6 * @see #setConfigLocations 7 * @see #afterPropertiesSet() 8 */ 9 public FileSystemXmlApplicationContext() { 10 } 11 12 /** 13 * Create a new FileSystemXmlApplicationContext for bean-style configuration. 14 * @param parent the parent context 15 * @see #setConfigLocation 16 * @see #setConfigLocations 17 * @see #afterPropertiesSet() 18 */ 19 public FileSystemXmlApplicationContext(ApplicationContext parent) { 20 super(parent); 21 } 22 23 /** 24 * 这个构造函数的configLocation包含的是BeanDefinition所在的文件路径 25 * Create a new FileSystemXmlApplicationContext, loading the definitions 26 * from the given XML file and automatically refreshing the context. 27 * @param configLocation file path 28 * @throws BeansException if context creation failed 29 */ 30 public FileSystemXmlApplicationContext(String configLocation) throws BeansException { 31 this(new String[] {configLocation}, true, null); 32 } 33 34 /** 35 * 这个构造函数允许configLocation包含多个BeanDefinition的文件路径 36 * Create a new FileSystemXmlApplicationContext, loading the definitions 37 * from the given XML files and automatically refreshing the context. 38 * @param configLocations array of file paths 39 * @throws BeansException if context creation failed 40 */ 41 public FileSystemXmlApplicationContext(String... configLocations) throws BeansException { 42 this(configLocations, true, null); 43 } 44 45 /** 46 * 这个构造函数在允许configLocation包含多个BeanDefinition的文件路径的同时,还允许指定 47 * 自己的双亲IoC容器 48 * Create a new FileSystemXmlApplicationContext with the given parent, 49 * loading the definitions from the given XML files and automatically 50 * refreshing the context. 51 * @param configLocations array of file paths 52 * @param parent the parent context 53 * @throws BeansException if context creation failed 54 */ 55 public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException { 56 this(configLocations, true, parent); 57 } 58 59 /** 60 * Create a new FileSystemXmlApplicationContext, loading the definitions 61 * from the given XML files. 62 * @param configLocations array of file paths 63 * @param refresh whether to automatically refresh the context, 64 * loading all bean definitions and creating all singletons. 65 * Alternatively, call refresh manually after further configuring the context. 66 * @throws BeansException if context creation failed 67 * @see #refresh() 68 */ 69 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException { 70 this(configLocations, refresh, null); 71 } 72 73 /** 74 * 在对象的初始化过程中,调用refresh函数载入BeanDefinition,这个refresh启动了 75 * BeanDefinition的载入过程,我们会在下面进行详细分析 76 * Create a new FileSystemXmlApplicationContext with the given parent, 77 * loading the definitions from the given XML files. 78 * @param configLocations array of file paths 79 * @param refresh whether to automatically refresh the context, 80 * loading all bean definitions and creating all singletons. 81 * Alternatively, call refresh manually after further configuring the context. 82 * @param parent the parent context 83 * @throws BeansException if context creation failed 84 * @see #refresh() 85 */ 86 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) 87 throws BeansException { 88 89 super(parent); 90 setConfigLocations(configLocations); 91 if (refresh) { 92 refresh(); 93 } 94 } 95 96 97 /** 98 * 这是应用于文件系统中Resource的实现,通过构造一个FileSystemResource来得到一个在文件 99 * 系统中定位的BeanDefinition 100 * 这个getResourceByPath是在BeanDefinitionReader的loadBeanDefinition中被调用的 101 * loadBeanDfinition采用了模板模式,具体的定位实现实际上是由各个子类来完成的 102 * 103 * 104 * Resolve resource paths as file system paths. 105 * <p>Note: Even if a given path starts with a slash, it will get 106 * interpreted as relative to the current VM working directory. 107 * This is consistent with the semantics in a Servlet container. 108 * @param path path to the resource 109 * @return Resource handle 110 * @see org.springframework.web.context.support.XmlWebApplicationContext#getResourceByPath 111 */ 112 @Override 113 protected Resource getResourceByPath(String path) { 114 if (path != null && path.startsWith("/")) { 115 path = path.substring(1); 116 } 117 return new FileSystemResource(path); 118 } 119 120 }
2.在FileSystemXmlApplicationContext中,我们可以看到在构造函数中,实现了对configuration进行处理的功能,让所有配置在文件系统中的,以XML文件方式存在的BeanDefinition都能够得到有效的处理,比如,实现了getResourceByPath方法,这个方法是一个模板方法,是为读取Resource服务的。
3.对于IoC容器功能的实现,这里没有涉及,因为它继承了AbstractXmlApplicationContext,关于IoC容器功能相关的实现,都是在FileSystemXmlApplicationContext中完成的,但是在构造函数中通过refresh来启动IoC容器的初始化,这个refresh方法非常重要,也是我们以后分析容器初始化过程实现的一个重要入口。
4.注意:FileSystemXmlApplicationContext是一个支持XML定义BeanDefinition的ApplicationContext,并且可以指定以文件形式的BeanDefinition的读入,这些文件可以使用文件路径和URL定义来表示。在测试环境和独立应用环境中,这个ApplicationContext是非常有用的。
5.根据图1的调用关系分析,我们可以清楚地看到整个BeanDefinition资源定位的过程。这个对BeanDefinition资源定位的过程,最初是由refresh来触发的,这个refresh的调用是在FileSystemXmlBeanFactory的构造函数中启动的,大致的调用过程如图2所示。
图1 getResourceByPath的调用关系
图2 getResourceByPath的调用过程