1.我们重点看看AbstractRefreshableApplicationContextrefreshBeanFactory方法的实现,这个refreshBeanFactoryFileSystemXmlApplicationContext构造函数中的refresh调用。在这个方法中,通过createBeanFactory构建了一个IoC容器供ApplicationContext使用。这个IoC容器就是我们前面提到过的DefaultListableBeanFactory,同时,它启动了loadBeanDefinitions来载入BeanDefinition,这个过程和前面以编程的方式来使用IoC容器(XmlBeanFacoty)的过程非常类似。

  1. protected final void refreshBeanFactory() throws BeansException {
  2. // 这里判断,如果已经建立了BeanFactory,则销毁并关闭该BeanFactory
  3. if (hasBeanFactory()) {
  4. destroyBeans();
  5. closeBeanFactory();
  6. }
  7. // 这里是创建并设置持有的DefaultListableBeanFactory的地方
  8. // 同时调用loadBeanDefinitions载入BeanDefinition的信息
  9. try {
  10. DefaultListableBeanFactory beanFactory = createBeanFactory();
  11. beanFactory.setSerializationId(getId());
  12. customizeBeanFactory(beanFactory);
  13. loadBeanDefinitions(beanFactory);
  14. synchronized (this.beanFactoryMonitor) {
  15. this.beanFactory = beanFactory;
  16. }
  17. }
  18. catch (IOException ex) {
  19. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  20. }
  21. }

AbstractRefreshableApplicationContext对容器的初始化

  1. // 这就是在上下文中创建DefaultListableBeanFactory的地方,而getInternalParentBeanFacoty()
  2. // 的具体实现可以
  3. // 查看AbstractApplicationContext中的实现,会根据容器已有的双亲IoC容器的信息来生成
  4. // DefaultListableBeanFactory的双亲IoC容器
  5. protected DefaultListableBeanFactory createBeanFactory() {
  6. return new DefaultListableBeanFactory(getInternalParentBeanFactory());
  7. }

createBeanFactory

  1. // 这里是使用BeanDefinitionReader载入Bean定义的地方,因为允许有多种载入方式,虽然用得
  2. // 最多的事XML定义的形式,这里通过一个抽象函数把具体的实现委托给子类来完成
  3. protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
  4. throws BeansException, IOException;

loadBeanDefinitions

  1. // 对于取得Resource的具体过程,我们可以看看DefaultResourceLoader是怎样完成的
  2. public Resource getResource(String location) {
  3. Assert.notNull(location, "Location must not be null");
  4. //
  5. if (location.startsWith("/")) {
  6. return getResourceByPath(location);
  7. }
  8. else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
  9. return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
  10. }
  11. else {
  12. try {
  13. // Try to parse the location as a URL...
  14. URL url = new URL(location);
  15. return new UrlResource(url);
  16. }
  17. catch (MalformedURLException ex) {
  18. // No URL -> resolve as resource path.
  19. return getResourceByPath(location);
  20. }
  21. }
  22. }

getResource

2.前面我们看到的getResourceByPath被子类FileSystemXmlApplicationContext实现,这个方法返回的是一个FileSystemResource对象,通过这个对象,Spring可以进行相关的I/O操作,完成BeanDefinition的定位。分析到这里已经一目了然,它实现的就是对path进行解析,然后生成一个FileSystemResource对象并返回,代码清单如下所示。

  1. protected Resource getResourceByPath(String path) {
  2. if (path != null && path.startsWith("/")) {
  3. path = path.substring(1);
  4. }
  5. return new FileSystemResource(path);
  6. }

FileSystemXmlApplicationContext生成FileSystemResource对象

3.如果是其他的ApplicationContext,那么会对应生成其他种类的Resource,比如ClassPathResource、ServletContextResource等。

4.关于Spring中Resource的种类,可以在图1的Resource类的继承关系中了解。作为接口Resource定义了许多与I/O相关的操作,这些操作也都可以从图1种的Resource的接口定义中看到。这些接口对不同的Resource实现代表着不同的意义,是Resource的实现需要考虑的。Resource接口的实现在Spring中的设计如图1所示。

图1 Resource的定义和继承关系

5.从图1中我们可以看到Resource的定位和它的继承关系,通过对前面的实现原理的分析,我们以FileSystemXmlApplicationContext的实现为例子,了解Resource定位问题的解决方案,即以FileSystem方式存在的Resource的定位实现。

6.在BeanDefinition定位完成的基础上,就可以通过返回的Resource对象来进行BeanDefinition的载入了。

7.在定位过程完成以后,为BeanDefinition的载入创造了I/O操作的条件,但是具体的数据还没有开始读入。这些数据的读入将在下面的BeanDefinition的载入和解析中来完成

8.任然以水桶为例子,这里就像用水桶去打水,要先找到水源。这里完成对Resource的定位,就类似于水源已经找到了,下面就是打水的过程了,类似于把找到的水装到水桶里的过程。找水不简单,但是与打水相比,我们发现打水更需要技巧。

BeanDefinition的Resource定位——3的更多相关文章

  1. Spring源码解析(二)BeanDefinition的Resource定位

    IOC容器的初始化过程主要包括BeanDefinition的Resource定位.载入和注册.在实际项目中我们基本上操作的都是ApplicationContex的实现,我们比较熟悉的ClassPath ...

  2. BeanDefinition的Resource定位

    1.以编程的方式使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefiniton.这时使用的是ClassPathResource,这意 ...

  3. IOC容器初始化——BeanDefinition的Resource定位

    以编程的方式使用DefaultListableBeanFactory时,首先定义一个Resource来定位容器使用的BeanDefinition.这是使用的是ClassPathResource,意味着 ...

  4. BeanDefinition的Resource定位——2

    1.FileSystemXmlApplicationContext的实现 public class FileSystemXmlApplicationContext extends AbstractXm ...

  5. Resource 定位、BeanDefinition 的载入和解析,BeanDefinition 注册。

    在前文提过,IOC 容器的初始化过程分为三步骤:Resource 定位.BeanDefinition 的载入和解析,BeanDefinition 注册. Resource 定位.我们一般用外部资源来描 ...

  6. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  7. Spring IOC容器的初始化—(一)Resource定位

    前言 上一篇博文“ Spring IOC是怎样启动的 ”中提到了refresh()方法,这个就是容器初始化的入口.容器初始化共有三个阶段: 第一阶段:Resource定位 第二阶段:BeanDefin ...

  8. Spring-IOC源码解读2.1-BeanDefinition的Resource定位

    Spring通过ResourceLoader来处理得到的Resource.在前面我们知道容器初始化是以refresh()方法为入口的,内部的实现首先准备上下文,然后通过obtainFreshBeanF ...

  9. BeanDefinition的载入和解析

    1.在完成对代表BeanDefinition的Resource定位的分析后,下面来了解整个BeanDefinition信息的载入过程. 2.对IoC容器来说,这个载入过程,相当于把定义的BeanDef ...

随机推荐

  1. 《TCP/IP具体解释卷2:实现》笔记--IP多播

    D类IP地址(224.0.0.0到239.255.255.255)不识别互联网内的单个接口,但识别接口组,被称为多播组. 单个网络上的组成员利用IGMP协议在系统之间通信. 多播路由器用多播选录协议. ...

  2. Angularjs Controller 间通信机制

    在Angularjs开发一些经验总结随笔中提到我们需要按照业务却分angular controller,避免过大无所不能的上帝controller,我们把controller分离开了,但是有时候我们需 ...

  3. 对javascript this的理解

    对于this的理解,大部分时间都比较模糊,最近几天做了一些研究,记录一下 首先应该明白,this是执行上下文的一个属性,它的值取决于执行上下文,执行上下文和函数调用方式相关,定义一个function的 ...

  4. windows 8.1 在硬盘上创建扩展分区

    管理员-命令提示符-> diskpart    -->进入分区工具. list disk     -->显示电脑连接磁盘数. select disk *  -->选择编号为*的 ...

  5. 查看Linux系统架构类型的5条常用命令

    导读 很多时候我们都需要查看当前 Linux 系统是 32 位还是 64 位系统架构类型,本文中我将向大家推荐 5 条常用命令.无论你使用的是桌面版或是只装了文本界面的 Linux 环境,以下命令几乎 ...

  6. python代码查询港澳通行证办理进度

    查询港澳通行证办理进度查询的python 3.3代码.利用socket请求相关网站,获得结果后利用正则找出办理进度.其实用urllib代码会更简洁,不过当时在下还不熟悉urllib~ 直接上代码: i ...

  7. 简约之美Jodd-http--应用一箩筐

    Jodd-http是一个微型的.简约的http client,然而简单而且方便.使用它可以轻松的实现发送请求和读取响应.它的目标就是日常应用变的非常简单,从而简化开发人员的工作. 了解Jodd-htt ...

  8. AllJoyn Bundled Daemon 使用方式研究

    关于AllJoyn不多做介绍,请看官网:www.alljoyn.org/ 0. 问题来源: 应用程序要使用AllJoyn库,就必须启动deamon. 目前有两种方式: 使用standalone形式,单 ...

  9. 小白日记45:kali渗透测试之Web渗透-SqlMap自动注入(三)-sqlmap参数详解-Optimization,Injection,Detection,Techniques,Fingerprint

    sqlmap自动注入 Optimization [优化性能参数,可提高效率] -o:指定前三个参数(--predict-output.--keep-alive.--null-connection) - ...

  10. JD轮播图代码

    <!DOCTYPE html>   <html>   <head>   <title>jd网站的轮播图效果</title>   <me ...