IoC:Inversion of Control,控制反转,即依赖对象的获得被反转了(DI:dependency inversion,依赖注入)
在Spring中,IoC容器是实现这个模式的载体。它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖。这种依赖注入是可以递归的,对象被逐层注入。
通过使用IoC容器,对象之间的相互依赖关系由IoC容器进行管理,并由IoC容器完成对象的注入。
IoC容器系列的设计与实现:BeanFactory和ApplicationContext
BeanFactory是简单容器系列,这系列容器只实现了容器的最基本功能
ApplicationContext应用上下文,它作为容器的高级形态而存在,增加了许多面向框架的特性,同时对应用环境作了许多适配。
BeanDefinition,是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕着这个BeanDefinition的处理来完成的。
IoC容器的初始化过程
1.Resource定位过程
这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。
2.BeanDefinition的载入
这个载入的过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。BeanDefinition实际上就是POJO对象在IoC容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对POJO对象也就是Bean进行管理。
如载入的是xml文件,文件中bean包含的id、name、aliase、property(如Array、List、Set、Map、Prop)等元素会一一加载到BeanDefinition中。
3.向IoC容器注册这些BeanDefinition的过程
这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。这个注册过程把载入过程中解析得到的BeanDefinition向IoC容器进行注册。通过分析,我们可以看到,在IoC容器内部将BeanDefinition注入到一个HashMap中去,IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。
以上谈的是IoC容器初始化的过程,在这个过程中,一般不包含Bean依赖注入的实现。Bean定义的载入和依赖注入是两个独立的过程,依赖注入一般发生在应用第一次通过getBean的时候(lazyinit属性可以对容器初始化过程作一个微小的控制)。
IoC容器的依赖注入
当用户向IoC容器索要Bean时,BeanFactory中的getBean方法的实现,就是触发依赖注入发生的地方。getBean接口方法由doGetBean最终实现,如果在当前BeanFactory中找不到bean,则到双亲BeanFactory中去取,还找不到则顺着双亲BeanFactory链一直向上查找。如果获取的bean有依赖的bean,会触发getBean的递归调用,直到取到一个没有任何依赖的bean为止。