犹豫了很久一直不敢开始写,在这个入职之日趁着无导师(导师出去浪了,具体去哪自己脑补吧)监督,零星记录点吧,作为自己的总结:
容器的基础XmlBeanFactory
bean是Spring中最核心的东西,因为Spring就像书架,你把bean放进书架里。谁会去使用就不关你的事了。因此我们从简单的getBean()方法入手吧。
applicationContext.xml是spring的配置文件,里面包含一个名为myTestBean的Bean。
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
MyTestBean bean = (MyTestBean) bf.getBean("myTestBean");
这是一个非常简单的Spring入门函数了。
先看BeanFactory的继承关系
*此图出自作者:钱书康。
* 出处:http://www.cnblogs.com/zrtqsk/p/4028453.html 这篇博客也很好,推荐大家去阅读。
为什么要从XmlBeanFactory开始说起呢,在Spring3.1以后XmlBeanFactory类被废除了,至于为什么会废除呢?有一下几点看法,希望以此能抛砖引玉真正的到XmlBeanFactory被废除的原因吧.
XmlBeanFactory继承自DefaultListableBeanFactory,而DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册及加载bean的默认实现,而对于XmlBeanFactory和DefaultListableBeanFactory不同的地方其实是在XmlBeanFactory中使用了自定义的XML读取器XmlBeanDefinitionReader,实现了个性化的BeanDefinitionReader读取。大家可以想想为什么会有很多标准制约我们,我们的东西是要给别人看而不是自娱自乐,这样就需要一份标准约束我们了。
我依然以XmlBeanFactory为基础讲解,这样读者可以更好的了解Spring,再者spring废除XmlBeanFactory最顶层实现类后,其他的继承关系没有发生变化,后续阅读不会产生任何影响。
这里也给出XmlBeanFactory废除后的写法:
时序图从BeanFactoryTest测试类开始,通过时序图我们可以一目了然地看到整个逻辑处理顺序。在测试的BeanFactoryTest中首先调用ClasspathResource的构造函数来构造Resource资源文件的实例对象,这样后续的资源处理就可以用Resource提供的各种服务来操作了。
配置文件的封装
在java中,将不同来源的资源抽象成URL,通过注册不同的handler来处理不同来源的资源的读取逻辑,一般handler的类型使用不同前缀来识别。
Spring的配置文件读取就是通过ClassPathResource进行封装的。因此Spring对其内部使用到的资源实现了自己的抽象结构:Resource接口来封装底层资源。那么我们一起来看看源码吧。
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
这些方法我就不再解释了,Spring最大的优点就是类和方法的命名通俗易懂,但正是这种命名方式使得Spring看起来就像讲故事一样,增加了阅读的难度。(个人看法勿喷【微笑】)。Resource接口抽象了所有Spring内部使用到的底层资源:File、URL、Classpath等。对不同来源的资源文件都有相应的Resource实现。有了Resource接口便可以对所有资源文件进行统一处理。至于实现就很简单了,以getInputStream为例,ClassPathResource中的实现方法便是通过class或者classLoader提供的底层方法进行调用,而对于FileSystemResource的实现其实更简单了,直接调用FileInputStream对文件进行实例化。
了解了Spring中将配置文件封装为Resource类型的实例方法后,我们将继续探寻XmlBeanFactory的初始化过程了。
构造函数的内部再次调用内部构造函数:
this.reader.loadBeanDefinitions(resource)才是资源加载的真正实现方法。但在加载数据之前我来讲解一下super(parentBeanFactory),代码跟踪到父类
ignoreDependencyInterface(BeanNameAware.class)的主要功能是忽略给定接口的自动装配功能。那么为什么要这么做呢?
举例说明吧,这样不至于太死板了。当A中有属性B,那么Spring在获取A的Bean的时候如果其属性B还没有初始化,那么Spring会自动初始化B,但某些情况下,B不会被初始化,那就是实现BeanNameAware接口。Spring在自动装配时忽略给定的依赖接口,典型应用就是通过其他方式解析Application上下文注册依赖,类似于BeanFactory通过BeanFactoryAware进行依赖注入或者ApplicationContext通过ApplicationContextAware进行注入。XXXAware通俗解释就是如果某各类里面想要使用Spring的一些东西就可以通过实现XXXAware接口,接收方式为setXxx();
加载Bean
我们接着this.reader.loadBeanDefinitions(resource)继续说,跟踪源码我来给大家梳理一下处理过程吧,Spring上层实现很简单,但到了底层就很复杂了。
1、封装资源文件。当进入XmlBeanDefinitionReader后首先对参数Resource使用EncodedResource类进行封装。EncodedResource是对资源文件的编码进行处理的。它的主要逻辑是
当设置了编码属性的时候Spring会使用相应的编码作为输入流的编码。
2、获取输入流。从Resource中获取对应的InputStream并构造InputSource。
3、通过构造的InputSource实例和Resource实例继续调用函数doLoadBeanDefinitions.
这么长的代码就做了三件事:(1)获取对XML文件的验证模式。(2)加载XML文件,并得到对应的Document.(3)根据返回的Document注册Bean信息。
今天就写到这吧 ,Spring的东西不能靠一篇博客就能说完的,明天继续搞,我先为后续的一篇博客介绍一下主体脉络吧。1、获取XML的验证方式。2、获取Document。3、解析及注册。
创作不易,转载请标明出处,谢谢