2.2 IOC容器系列的设计与实现:BeanFactory 和 applicationContext
Spring的IOC容器设计中,有两个主要的容器系列
一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本的功能;
另一个是ApplicationContext应用上下文,作为容器的高级形态而存在。在简单容器的基础上,增加了许多面向框架的特性,对应用环境作了许多的适配。
##2.2.1 spring的IOC容器系列
Spring的IOC容器系列Resource和它的子类
作为IOC容器,它的具体实现指定基本的功能规范,就是接口类BeanFactory,为用户使用的IOC容器所设定的最基本的功能规范。
Resource相当于水桶(IOC容器),BeanFactory定义了水桶最基本的功能。而Spring的的具体IOC容器需要满足BeanFactory这个基本的接口定义。
在spring提供IOC容器的接口定义和实现的基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。抽象了我们对Bean的定义,是让容器起作用的主要数据类型。
2.2.2 IOC容器的设计
接口路线1. BeanFactory到ConfigurableBeanFactory
BeanFactory: 定义了基本的IOC容器规范
HierarchicalBeanFactory:增加getParentBeanFactory的接口功能,具备双亲IOC容器的管理功能。
ConfigurableBeanFactory:主要定义了一些对BeanFactory的配置功能,如setParentBeanFactory设置双亲IOC容器,addBeanPostProcessor增加Bean后置处理器等。
接口路线2. ApplicationContext应用上下文接口为核心的接口设计
我们常用的应用上下文基本上都是ConfigurableAplicationContext和WebApplicationContext的实现。
ListableBeanFactory:细化了许多BeanFactory的接口功能,如getBeanDefinitionNames接口方法
ApplicationContext:通过继承许多接口,在BeanFactory简单IOC容器的基础上做了扩展。
BeanFactory的应用场景
用户使用容器时可以&来得到FactoryBean本身,用来区分通过容器来获取FactoryBean产生的对象和获取FactoryBean本身。
FactoryBean:IOC容器管理,但不是普通的Bean,而是一个能产生和修饰对象生成的工厂Bean。它的设计和工厂模式和修饰器模式类似。
getBean方法:通过名字来索引取得IOC管理的Bean,同时也可以对Bean的类型做检查。
有了BeanFactory的定义,用户可以执行以下的操作
- containsBean
- isSingleton
- isPrototype
- isTypeMatch Bean是否为指定类型
- getType 查询指定Bean的class类型
- getAliases 查询指定Bean的所有别名,在BeanDefinitions中定义的
XMLBeanFactory入手IOC设计原理
AbstracyBeanFactory -> AbstractAutowiredCapableBeanFactory -> DefaulistableBeanFactory-> XMLBeanFactory
DefaulistableBeanFactory: 是一个默认的功能完整的IOC容器,XMLBeanFactory继承于他,并且增加了读取XML文件方式定义BeanDefinition的方法。
XMLBeanFactory: 初始化了XMLBeanDefinitionReader来对XML文件进行信息处理的。构造XMLBeanFactory,需要指定BeanDefinition的信息来源,而这个信息来源需要封装成spring中的Resource类(就是上面所说的水桶)中给出,Resource是Spring用来封装I/O操作的类,例: ClassPathResource res = new classPathResource("bean.xml")
ClassPathResource: 用具体的ClassPathResource来构造Resource,将Resource作为构造参数传递给XMLBeanDefinition。使得IOC容器可以定位BeanDefinition完成容器的初始化和依赖注入的过程。
其代码如下
@Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory {
// XMLReader,有
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* Create a new XmlBeanFactory with the given resource,
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
/**
* 获取Resource对象,初始化XmlBeanDefinitionReader,调用loadBeanDefinitions传入Resource来初始化和加载Bean
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
编程式使用IOC容器
// 指定BeanDefinition地址
ClassPathResource res = new ClassPathResource("bean.xml");
DefaultListableBeanFactory factory = new DefaultListableFactory();
// 初始化Reader
XMLBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanfinitions(res);
步揍如下
- 创建IOC配置文件的抽象资源,包含了BeanDefinition的定义信息
- 创建一个BeanFactory,这里使用DefaultListableBeanFactory
- 创建一个载入BeanDefinition的读取器XMLBeanDefinitionReader,回调配置给BeanFactory
- 从定义好的资源位置读入配置信息,具体的解析过程有XMLBeanDefinitionReader来完成,完成载入和注册Bean定义之后,IOC容器就建立起来了。
ApplicationContext的应用场景
除了上述的建立过程,为了方便客户使用,Spring已经提供了ApplicationContext为开发者使用,还为用户提供了附加服务。
提供的新特性
- 扩展了MessageSource接口,支持国际化实现
- 访问资源,支持ResourceLoader和Resource,可以从不同地方获取Bean定义。
- 支持应用事件,实现了ApplicationEventPublisher,在上下文引入事件机制,为Bean的管理提供便利。
FileSystemXmlApplicationContext的实现来学习ApplicationContext:
可以看到,AbstractApplicationContext实现了ConfigurableApplicationContext,其实现了ApplicationContext的基本功能。而FileSystemXmlApplicationContext作为一个具体的应用上下文,只需要实现基类AbstractApplicationContext和自身设计相关的两个功能。
如果一个应用直接使用FileSystemApplicationContext,对于实例化这个应用的上下文的支持,同时启动IOC容器的refresh()过程