Spring 深入——IoC 容器 02

IoC容器的实现学习——02目录

  • IoC容器的实现学习——02
    • 回顾
    • IoC 容器的初始化过程:
      • BeanDefinition 的 Resource 定位
        • 小结:
回顾前面学习了 IoC 模式的核心概念 , 使用场景 , 以及 Spring 对 IoC
具体实现的两种系列:BeanFactory 和 ApplicationContext
通过两种系列的具体 IoC 容器来帮助我们了解了两个不同的特点 , 以及面向不同的场景 。有利有弊 , 在开发中需要根据具体需求选择合适的 IoC 具体实现 。
其中也通过对 Spring IoC 的具体实现的简单分析 , 对 IoC 设计的有了初步的了解和想法 。那么现在就来开始了解 IoC 容器初始化的过程 。
IoC 容器的初始化过程:前面在学习 FileSystemXmlApplicationContext 的时候 , 构造方法中通过此类调用了 refresh() 方法 。IoC 容器的初始化实际上就是通过这个方法来启动的 , 标志着 IoC 容器正式启动 。
IoC 容器的启动包括以下三个基本过程:
  1. BeanDefinition 资源的定位
  2. ~ 的载入
  3. ~ 的注册
期间需要注意的是这是一个顺序过程 , 同时指的是 IoC 容器的初始化 , 而 Bean 的依赖注入的实现 , 一般不包括其中 , 但是 BeanDefiniton 有一个 lazyinit 的属性 , 用户可以通过这个属性改变 Bean 的依赖注入过程 , eg:一般情况下 Bean 的注入需要在容器初始化之后 , 第一次调用 getBean() 时才会触发 , 而通过 lazyinit 属性可以让 Bean 在 IoC 容器初始化时就预先完成了依赖注入 。
BeanDefinition 的 Resource 定位根据前面的学习 , 我们这一过程的表层应该不难知晓 , 就是通过定义一个 Resuorce 去定位容器使用的 BeanDefinition 。eg:ClassPathResource() 这个类就是在项目中的类路径中寻找以文件形式存在的 BeanDefinition 。
应该注意的是 , 不能把 Resource 的定位 BeanDefinition 资源和 BD 的载入弄混淆了 。只是定位资源而已 , 此时 IoC 容器还不能直接使用这些信息 , 这些信息是交由 BeanDefinitionReader 来对这些信息进行 BD 的载入处理 。
相对于 DefaultListableBeanFactory 容器需要手动配置好特定的 Resource 读取器 , ApplicationContext 容器就准备好了一系列的读取器 。
但是使用 DefaultListableBeanFactory 这种底层容器可以根据业务定制 IoC 容器的灵活性 , 有利有弊 。
还是通过 FileSystemXmlApplicationContext 这一具体容器来分析是如何完成 Resource 的定位过程 。
继承体系:
【Spring 深入——IoC 容器 02】
Spring 深入——IoC 容器 02

文章插图
主要两个功能的源码:
Spring 深入——IoC 容器 02

文章插图
上图表明了getResourceByPath()是实现 Resource 定位的方法 。但是并不是使用者调用的 , 查看该方法的调用链:
Spring 深入——IoC 容器 02

文章插图
上图标注了该方法最初是由 refresh() 方法触发的 , 而 refresh() 是在构造器中调用的 。
我们需要通过这个方法来了解过程 。
构造器调用的是超类 AbstractApplicationContext 中的 refresh() , 查看源码:
public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {this.prepareRefresh();// 创建beanFactory以及扫描bean信息(beanDefinition) , 并通过BeanDefinitionRegistry 注册到容器中 。ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 省略...}}

经验总结扩展阅读