配置文件封装
Spring的配置文件读取是通过ClassPathResorce进行封装的,如new ClassPathResource("beanFactoryTest.xml")。
在Java中,将不同来源的资源抽象成URL,通过注册不同的handler(UrlStreamHandler)来处理不同来源的资源的读取逻辑,一般handler的类型使用不同前缀(协议,Protocol)来识别,如:"file:"、"http:"、"jar:"等,然而URL没有默认定义相对ClassPath或者ServletContext等资源的handler,虽然可以通过注册自己的URLStreamHandler来解析特定的URL前缀(协议),比如"classPath:",然而这需要了解URL的实现机制,而且URL也没有提供一些基本的方法,比如检查当前资源是否存在、检查当前资源是否可读等方法。因而Spring对其内部使用到的资源实现了自己的抽象结构:Resource借口来封装底层资源。
InputStreamSource封装任何能返回InputStream的类,比如File、ClassPath下的资源和Byte Array等。它只有一个方法定义:getInputStream(),该方法返回一个新的InputStream对象。
Resource接口抽象了所有Spring内部使用到的底层资源:File、URL、ClassPath等。对不同来源的资源文件都有对应的Resource实现:文件(FileSystemResource)、ClassPath资源(ClassPathResource)、URL资源(URLResource)、InputStream资源(InputStreamResource)、Byte数组(ByteArrayResource)等。
当通过Resource相关类完成对配置文件的封装后配置文件的读取工作就全权交给XmlBeanDefinitionReader来处理了。
在将配置文件封装为Resource类型的实例后即可使用Resource实例作为构造函数的参数进行构造XmlBeanFactory。
加载bean
XmlBeanFactory构造函数中调用了XmlBeanDefinitionReader类型的reader属性提供的方法this.reader.loadBeanDefinitions(resource),而这句代码则是整个资源加载的切入点,之后的流程大致如下:
(1)封装资源文件。当进入XmlBeanDefinitionReader后首先对参数Resource使用EncordedResource类进行封装。
(2)获取输入流。从Resource中获取对应的InputStream并构造InputSource
(3)通过构造的InputSource实例和Resouce实例继续调用函数doLoadBeanDefinition。