IOC的两种实现方式

IOC的两种实现方式

  1. 构造方法注入
  2. setter注入

Ioc需要实现两个技术:
- 对象的构建
- 对象的绑定

spring提供了两种类型的容器,一个是BeanFactory,一个是ApplicationContext(可以认为是BeanFactory的扩展),下面我们将介绍这两种容器如何实现对对象的管理。

BeanFactory

如果没有特殊指定,默认采用延迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管对象的时候,才对该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的 IoC容器选择。

我们先来看一下BeanFactory的关系图
IOC的两种实现方式

有三个很重要的部分:

  • BeanDefinition 实现Bean的定义(即对象的定义),且完成了对依赖的定义
  • BeanDefinitionRegistry ,将定义好的bean,注册到容器中(此时会生成一个***)
  • BeanFactory 是一个bean工厂类,从中可以取到任意定义过的bean 。

最重要的部分就是BeanDefinition,它完成了Bean的生成过程。一般情况下我们都是通过配置文件(xml,properties)的方式对bean进行配置,每种文件都需要实现BeanDefinitionReader,因此是reader本身现了配置文字 到bean对象的转换过程。当然我们自己也可以实现任意格式的配置文件,只需要自己来实现reader即可。

Bean的生成大致可以分为两个阶段:容器启动阶段和bean实例化阶段

IOC的两种实现方式

容器启动阶段:
- 加载配置文件(通常是xml文件)
- 通过reader生成beandefinition
- beanDefinition注册到beanDefinitionRegistry

bean实例化阶段:

当某个bean 被 getBean()调用时

bean需要完成初时化,以及其依赖对象的初始化

如果bean本身有回调,还需要调用其相应的回调函数

从上面我们也可以知道,beanDefinition(容器启动阶段)只完成bean的定义,并未完成初始化。初始是通过beanFactory的getBean()时才进行的。

Bean的初始化过程

IOC的两种实现方式

实例化的bean对象并不是new出来的,而是通过反射机制生成了代理对象。

完成设置对象属性之后,则会检查是否实现了Aware类型的接口,如果实现了,则主动加载
BeanPostprocessor 可以帮助完成在初始化bean之前或之后 帮我们完成一些必要工作,比如我们在连接数据库之前将密码存放在一个加密文件,当我们连接数据库之前,需要将密码进行加载解密。只要实现 相应的接口即可

ApplicationContext

ApplicationContext 容器建立BeanFactory之上,拥有BeanFactory的所有功能,但在实现上会有所差别。我认为差别主要体现在两个方面:1.bean的生成方式;2.扩展了BeanFactory的功能,提供了更多企业级功能的支持。

bean的加载方式

BeanFactory提供BeanReader来从配置文件中读取bean配置。相应的ApplicationContext也提供几个读取配置文件的方式:

  • FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径
  • ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
  • WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
  • AnnotationConfigApplicationContext
  • ConfigurableWebApplicationContext

另外一个比较重要的是,ApplicationContext采用的非懒加载方式。它会在启动阶段完成所有的初始化,并不会等到getBean()才执行。所以,相对于BeanFactory来 说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容 器启动时间较之BeanFactory也会长一些。在那些系统资源充足,并且要求更多功能的场景中, ApplicationContext类型的容器是比较合适的选择。
IOC的两种实现方式

ResourceLoader

ResourceLoader并不能将其看成是Spring独有的功能,spring Ioc只是借助于ResourceLoader来实现资源加载。也提供了各种各样的资源加载方式:
- DefaultResourceLoader 首先检查资源路径是否以classpath:前缀打头,如果是,则尝试构造ClassPathResource类 型资源并返回。否则, 尝试通过URL,根据资源路径来定位资源
- FileSystemResourceLoader 它继承自Default-ResourceLoader,但覆写了getResourceByPath(String)方法,使之从文件系统加载资源并以 FileSystemResource类型返回