Spring源码解析(一)

犹豫了很久一直不敢开始写,在这个入职之日趁着无导师(导师出去浪了,具体去哪自己脑补吧)监督,零星记录点吧,作为自己的总结:

容器的基础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、解析及注册。

创作不易,转载请标明出处,谢谢

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值