控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另外一种说法。没有IoC的程序中咱们使用面向对象编程对象的建立与对象间的依赖关系彻底硬编码在程序中,对象的建立由程序本身控制,控制反转后将对象的建立转移给第三方(容器),所谓的控制反转就是:得到依赖对象的方式反转了。spring
IOC的思想核心的地方在于,资源不禁使用资源的双方管理,而由不使用资源的第三方管理,这能够带来不少好处。第一,资源集中管理,实现资源的可配置和易管理。第二,下降了使用资源双方的依赖程度,也就是咱们说的耦合度。编程
Spring IOC设计中,主要有两个容器系列(下图):一是实现BeanFactory接口的简单容器,仅实现了最基本的功能;二是ApplicationContext应用上下文,做为容器的高级形态,增长了面向框架的特性。数据结构
Spring经过定义BeanDefinition来管理基于Spring的应用中的各类对象以及它们之间的依赖关系。IOC容器是用来管理对象依赖关系的,对于IOC容器来讲,BeanDefinition就是对依赖反转模式中管理对象关系的数据抽象(核心数据结构)。BeanDefinition就像容器装的水,有了基本数据,容器才能发挥做用。框架
BeanFactory接口定义了IOC容器最基本的形式,提供使用IOC容器所须要遵照的最底层和最基本的编程规范。编码
BeanFactory是个Factory,也就是IOC容器或对象工厂。最主要的方法就是getBean(String beanName),该方法从容器中返回特定名称的Bean,只不过其中有一种Bean是FacotryBean。spa
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。继承
这里以XMLBeanFactory为例,初始化过程:递归
1.建立IOC配置文件的抽象资源,包括BeanDefinition的定义信息。
2.建立一个BeanFactory,这里使用DefaultListableBeanFactory。
3.建立一个载入BeanDefinition的读取器,这里使用XMLBeanDefinitionReader来载入XML文件形式的BeanDefinition,经过一个回调配置给BeanFactory。
4.从定义好的资源位置载入配置信息,具体的解析过程由XMLBeanDefinitionReader来完成。完成整个载入和注册Bean定义以后,须要的IOC容器就简历起来了。这个时候就可使用IOC容器了。
ApplicationContext是一个高级形态意义的IOC容器,提供了如下特性:
1.支持不一样的信息源。扩展MessageResource接口,例如支持国际化实现。
2.访问资源。对ResourceLoader和Resource支持,可从不一样的地方获取Bean定义资源。
3.支持应用事件。继承了接口ApplicationEventPublisher,在上下文引入事件机制。
4.在ApplicationContext中提供附加服务。使其具备面向框架的使用风格。
完成BeanDefinition注册后,就完成了IOC容器的初始化过程,此时已经创建了整个Bean的配置信息,BeanDefinition已经能够被使用了,都在beanDefinitionMap里被检索和使用。容器的做用就是对这些信息进行处理和维护。
依赖注入的过程是用户第一次向IOC容器索要Bean(getBean)时触发,也可在BeanDefinition经过控制lazy-init属性来让容器完成对Bean的预实例化。
在Bean的建立和对象依赖注入的过程当中,须要根据BeanDefinition中的信息来递归的完成依赖注入。递归都是以getBean为入口。一个递归是在上下文中查找须要的Bean和建立Bean的递归调用;另外一个递归是在依赖注入时,经过递归调用容器订单getBean方法,获得当前Bean的依赖Bean,同时出发对依赖Bean的建立和注入。
在Bean建立和对象依赖注入完成之后,在IOC容器中创建起一系列依靠依赖关系联系起来的Bean, 经过IOC容器的相关接口方法,就能够很是方便的供上层应用使用了。