Spring的 IoC容器设计和实现

IoC的设计中有两个主要的容器系列:

(1) 实现BeanFactory接口的简单容器系列,只实现了容器的最基本功能;

(2) ApplicationContext应用上下文,它作为容器的高级形态而存在。

应用上下文在简单容器的基础上增加了面向框架的特性,同时对应用环境做了许多适配。

2.2.1 Spring的IoC容器系列

通常所说的IoC容器实际上代表着一系列功能不同的容器产品,就好比商店卖的水桶,他们的大小、制作材料等都不同,但是他们的基本特性就是能装水。商品需要产品规格说明,IoC容器也有它的基本功能规范,它就是接口类BeanFactory。就好比水桶最基本的功能就是装水,IoC容器需要满足BeanFactory这个最基本的接口定义。

BeanDefinition抽象了我们对Bean的定义,将Bean的定义信息存储到这个BeanDefinition相应的属性中,后面对Bean的操作就直接对BeanDefinition进行,例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建。BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,如ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。

2.2.2 Spring的IoC容器设计

这里介绍两条接口设计主线:

(1) BeanFactory_HierarchicalBeanFactory_ConfigurableBeanFactory

这条线路中,BeanFactory接口定义了IoC容器的基本规范,比如getBean()这样的方法。而HierarchicalBeanFactory接口在继承BeanFactory之后,增加了getParentBeanFactory()的接口功能,使BeanFactory具备双亲IoC容器的管理功能。ConfigurableBeanFactory中定义了对BeanFactory的配置功能,如通过setParentBeanFactory()设置双亲IoC容器,通过addBeanPostProcessor()配置Bean后置处理器等。

(2) BeanFactory_ListableBeanFactory_ApplicationContext_WebApplicationContext(ConfigurableApplicationContext)

上图所示是主要接口关系,具体的IoC容器都是在这个接口体系下实现的。这个接口系统是以BeanFactory和ApplicationContext为核心,在上图可以看到,一方面,ApplicationContext继承了BeanFactory接口体系中的ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory,具备了BeanFactory的基本功能;另一方面,通过继承MessageSource、ResourceLoader、ApplicationEventPublisher接口,又赋予了ApplicationContext更高级的IoC容器特性。

1. BeanFactory的应用场景

用户使用容器时,可以用转义符“&”来得到FactoryBean本身,这与通过容器获取FactoryBean产生的对象不同。比如A是一个FactoryBean,那么&A得到的是FactoryBean,而不是A这个FactoryBean产生出来的对象。

PS:BeanFactory是Factory,它是IoC容器或对象工厂;FactoryBean是Bean;在Spring中,所有的Bean都由BeanFactory(IoC容器)进行管理,而FactoryBean不是一个简单的Bean,它是一个能产生或修饰对象生成的工厂Bean,它的实现类似于工厂模式和修饰器模式。

有了BeanFactory的定义,用户可以执行以下操作:

(1) 通过接口方法cotainsBean让用户能够判断容器是否含有指定名字的Bean。

(2) 通过接口方法isSingleton来查询指定名字的Bean是否是Singleton类型的Bean。对于Singleton属性,用户可以在BeanDefinition中指定。

(3) 通过接口方法isProtopyte来查询指定名字的Bean是否是Protopyte类型的Bean。对于Protopyte属性,用户同样可以在BeanDefinition中指定。

(4) 通过接口方法isTypeMatch来查询指定了名字的Bean的Class类型是否是特定的Class类型。这个Class类型可以由用户来指定。

(5) 通过接口方法getType来查询指定名字的Bean的Class类型。

(6) 通过接口方法getAliases来查询指定了名字的Bean的所有别名,这些别名都是用户在BeanDefinition中定义的。

2. BeanFactory的设计原理

XmlBeanFactory继承自DefaultListableBeanFactory这个类,这个类非常重要,它实际上包含了基本IoC容器具有的重要功能,XmlBeanFactory在继承它的同时,增加了新功能,它可以读取以Xml文件方式定义的BeanDefinition的IoC容器。如何读取?在XmlBeanFactory中初始化了一个XmlBeanFactoryReader的对象,由它来完成。

构造XmlBeanFactory时,需要指定BeanDefinition的信息来源,并需要封装成Spring中的Resource类(这个类是Spring用来封装I/O操作的类)。把Resource作为构造参数传给XmlBeanFactory构造函数,这样IoC容器就可以方便定为到需要的BeanDefinition来对Bean完成容器的初始化和依赖注入。

public class XmlBeanFactory extends DefaultListableBeanFactory {
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader.loadBeanDefinitions(resource);
    }
}

猜你喜欢

转载自my.oschina.net/u/3342874/blog/1813753