在面向对象系统中,对象封装了数据和对数据的处理,对象的依赖关系常常体现在对数据和方法的依赖上。这些依赖关系可以通过把对象的依赖注入交给框架或IOC容器来完成,这种从具体对象手中交出控制的做法是非常有价值的,它可以在解耦代码的同时提高代码的可测试性。
在Spring中,IoC容器是实现这个模式的载体,它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖。setter注入和构造器注入是主要的注入方式。
IoC容器系列的设计与实现:BeanFactory和ApplicationContext
1、从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一个主要的BeanFactory设计路径。这个接口定义中,包括了getBean()这样的IOC容器的基本方法,通过这个方法可以从容器中取得Bean。ConfigurableBeanFactory接口中,主要定义了一些对BeanFactory的配置功能,比如通过setParentBeanFactory()设置双亲IoC容器,通过addBeanPostProcessor配置Bean后置处理等等。
2、以ApplicationContext应用上下文为核心的接口设计,主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到我们常用的WebApplicationContext或者ConfigurableApplicationContext接口。我们常用的应用上下文基本上都是ConfigurableApplicationConntext或者WebApplicationContext的实现。
BeanFactory接口设计了getBean方法,这个方法是使用IoC容器API的主要方法,通过这个方法,可以取得IoC容器中管理的Bean。如果需要在获取Bean时对Bean进行类型检查,则可用带参数的方法。Object getBean(String name,Class requiredType);
接口清单:
那么Spring中XML的读取功能是怎样实现的呢?
构造XmlBeanFactory这个IoC容器时,需要指定BeanDefinition的信息来源,而这个信息来源需要封装成Spring中的Resource类来给出。Resource类是Spring用来封装I/O操作的类。
IoC容器的初始化过程
IoC的启动包括BeanDefinition的Resource定位、注入和注册三个基本过程。
第一个过程是Resource定位过程。这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成。
第二个过程是BeanDefinition的载入。这个载入过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。
第三个过程是向IoC容器注册这些BeanDefinition的过程。在IoC容器内部将BeanDefinition注入到一个HashMap中去,IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。
Spring IoC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。但有个例外,就像我们向某个Bean设置了lazyinit属性,那么这个Bean的依赖注入在IoC容器初始化时就预先完成了,而不需要等到整个初始化完成以后,第一次使用getBean时才会触发。