Spring之IOC容器实现

    IOC简介

    控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方(容器),所谓的控制反转就是:获得依赖对象的方式反转了。

    IOC的思想核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

    Spring IOC设计中,主要有两个容器系列(下图):一是实现BeanFactory接口的简单容器,仅实现了最基本的功能;二是ApplicationContext应用上下文,作为容器的高级形态,增加了面向框架的特性。

    Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的依赖关系。IOC容器是用来管理对象依赖关系的,对于IOC容器来说,BeanDefinition就是对依赖反转模式中管理对象关系的数据抽象(核心数据结构)。BeanDefinition就像容器装的水,有了基本数据,容器才能发挥作用。

BeanFactory

    BeanFactory接口定义了IOC容器最基本的形式,提供使用IOC容器所需要遵守的最底层和最基本的编程规范。

BeanFactory与FactoryBean

    BeanFactory是个Factory,也就是IOC容器或对象工厂。最主要的方法就是getBean(String beanName),该方法从容器中返回特定名称的Bean,只不过其中有一种Bean是FacotryBean。

    FactoryBean 是一种特殊的bean,实际上也是一个工厂,通过FactoryBeanName得到FacotryBean创建的Bean,它通过getObject()创建的Bean。要想得到FactoryBean本身,必须通过&FactoryBeanName得到,即在BeanFactory中通过getBean(&FactoryBeanName)来得到 FactoryBean。

注:在spring 中是通过BeanFactoryUtils.isFactoryDereference()来判断一个Bean是否是FactoryBean.

spring 内部实现中应该是在通过BeanFacotry 的getBean(String beanName) 来得到Bean时,如果这个Bean是一个FactoryBean,则把它生成的Bean返回,否者直接返回Bean。

BeanFactory容器的实现原理

 这里以XMLBeanFactory为例,初始化过程:

1.创建IOC配置文件的抽象资源,包括BeanDefinition的定义信息。

2.创建一个BeanFactory,这里使用DefaultListableBeanFactory。

3.创建一个载入BeanDefinition的读取器,这里使用XMLBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory。

4.从定义好的资源位置载入配置信息,具体的解析过程由XMLBeanDefinitionReader来完成。完成整个载入和注册Bean定义之后,需要的IOC容器就简历起来了。这个时候就可以使用IOC容器了。

ApplicationContext

    ApplicationContext是一个高级形态意义的IOC容器,提供了以下特性:

    1.支持不同的信息源。扩展MessageResource接口,例如支持国际化实现。

    2.访问资源。对ResourceLoader和Resource支持,可从不同的地方获取Bean定义资源。

    3.支持应用事件。继承了接口ApplicationEventPublisher,在上下文引入事件机制。

    4.在ApplicationContext中提供附加服务。使其具有面向框架的使用风格。

BeanDefinition注册

    完成BeanDefinition注册后,就完成了IOC容器的初始化过程,此时已经建立了整个Bean的配置信息,BeanDefinition已经可以被使用了,都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。

IOC容器依赖注入

    依赖注入的过程是用户第一次向IOC容器索要Bean(getBean)时触发,也可在BeanDefinition通过控制lazy-init属性来让容器完成对Bean的预实例化。

    在Bean的创建和对象依赖注入的过程中,需要根据BeanDefinition中的信息来递归的完成依赖注入。递归都是以getBean为入口。一个递归是在上下文中查找需要的Bean和创建Bean的递归调用;另一个递归是在依赖注入时,通过递归调用容器订单getBean方法,得到当前Bean的依赖Bean,同时出发对依赖Bean的创建和注入。

    在Bean创建和对象依赖注入完成以后,在IOC容器中建立起一系列依靠依赖关系联系起来的Bean, 通过IOC容器的相关接口方法,就可以非常方便的供上层应用使用了。

猜你喜欢

转载自my.oschina.net/u/1765168/blog/1800087