IOC的理解

 

IOC的两种实现方式
构造方法注入

setter注入

接口注入

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

 

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

 

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

 

我们先来看一下BeanFactory的关系图

 


有三个很重要的部分:

 

BeanDefinition 实现Bean的定义(即对象的定义),且完成了对依赖的定义
BeanDefinitionRegistry ,将定义好的bean,注册到容器中(此时会生成一个注册码)
BeanFactory 是一个bean工厂类,从中可以取到任意定义过的bean 。
最重要的部分就是BeanDefinition,它完成了Bean的生成过程。一般情况下我们都是通过配置文件(xml,properties)的方式对bean进行配置,每种文件都需要实现BeanDefinitionReader,因此是reader本身现了配置文字 到bean对象的转换过程。当然我们自己也可以实现任意格式的配置文件,只需要自己来实现reader即可。

 

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

 

 

 

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

 

bean实例化阶段:

 

当某个bean 被 getBean()调用时

 

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

 

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

 

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

 

Bean的初始化过程

 


实例化的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类型的容器是比较合适的选择。

 


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

DI是什么

利用interface的方式,可以让类在使用的时候再决定由哪个具体类来实现。那该如何实现这种方式呢?这时就有一个新的名称出现了,就是Dependency Injection(依赖注入),简称DI。DI有三种方式,分别是构造函数注入、属性注入、接口注入.

IoC与DI的关系

我的理解是IoC是一种理念,DI则是它的具体实现方式

IoC Container

IoC Container帮我们在项目运行时动态的创建实例,它主要功能如下:

  • 动态创建、注入依赖对象
  • 管理对象生命周期
  • 映射依赖关系

IoC Container技术实现的原理就是“反射(Reflection)”。利用反射动态的创建对象,把依赖关系注入到指定对象中。一般常用的注入方式是构造函数注入和属性注入

Service Locator模式

服务定位模式也是IoC理念的一种实现。实现原理:通过ServiceLocator类提供实现IServiceLocator接口的单例,并负责管理已注册实例的创建和访问。通常结合工厂模式来结合使用。 
Service Locator与IoC Container都是IoC的具体实现方式。不同的是Service Locator没有提供管理对象生命周期的功能

posted @ 2018-10-26 15:31  ng-xixi  阅读(298)  评论(0编辑  收藏  举报