Spring Ioc容器的设计:BeanFactory和ApplicationContext

Spring Ioc容器的设计

在Spring Ioc容器的设计中,有两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,只实现了容器的最基本的功能;另一个是ApplicationContext应用上下文,进行了很多扩展,它作为容器的高级形态存在。

Spring Ioc容器的设计:。。。。

BeanFactory容器的设计原理(以 实现类XmlBeanFactory为例):

083622_ZZ0B_3723612.png

public class XmlBeanFactory extends DefaultListableBeanFactory
{

    public XmlBeanFactory(Resource resource)
        throws BeansException
    {
        this(resource, null);
    }

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
        throws BeansException
    {
        super(parentBeanFactory);
        reader = new XmlBeanDefinitionReader(this);
        reader.loadBeanDefinitions(resource);
    }

    private final XmlBeanDefinitionReader reader;
}

在Spring中,实际上是把DefaultListableBeanFactory作为一个默认的功能完整的Ioc容器来使用。XmlBeanFactory容器继承了DefaultListableBeanFactory又增加了一些新的功能。XmlBeanFactory是一个与XML相关的BeanFactory,是一个可以读取以XML文件方式定义的BeanDefinition(XML定义的信息)的Ioc容器。

BeanDefinition分为FileSystemResource(文件系统中的Bean定义的信息可以使用FileSystemResource来进行抽象)、ClassPathResource(在类路径中的Bean定义信息可以使用ClassPathResource来使用)等

实现XML读取的功能实现:对这些XML形式的信息处理并不是直接通过XmlBeanFactory直接完成。从上面XmlBeanFactory的代码中可以看出初始化了一个XmlBeanDefinitionReader对象,对XML形式的信息处理实际上是由XmlBeanDefinitionReader(Reader对象)来完成的。

构造XmlBeanFactory这个Ioc容器时,需要指定BeanDefinition的信息来源,需要被封装成Spring中的Resource类给出。Resource是Spring用来封装I/O操作的类。BeanDefinition信息是以XML文件形式存在的,可以使用像ClassPathResource res = new ClassPathResource("beans.xml");这样具体的ClassPathResource来构造需要的Resource,然后将Resource作为构造参数传递给XmlBeanFactory构造函数。这样,Ioc容器就可以方便地定位到需要的BeanDefinition信息来对Bean完成容器的初始化和依赖注入过程。

ApplicationContext容器的设计原理(FileSystemXmlApplicationContext为例):

ApplicationContext与FileSystemXmlApplicationContext关系图:

080401_nFGT_3723612.png

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext
{

    public FileSystemXmlApplicationContext()
    {
    }

    public FileSystemXmlApplicationContext(ApplicationContext parent)
    {
        super(parent);
    }

    public FileSystemXmlApplicationContext(String configLocation)
        throws BeansException
    {
        this(new String[] {
            configLocation
        }, true, null);
    }

    public transient FileSystemXmlApplicationContext(String configLocations[])
        throws BeansException
    {
        this(configLocations, true, null);
    }

    public FileSystemXmlApplicationContext(String configLocations[], ApplicationContext parent)
        throws BeansException
    {
        this(configLocations, true, parent);
    }

    public FileSystemXmlApplicationContext(String configLocations[], boolean refresh)
        throws BeansException
    {
        this(configLocations, refresh, null);
    }
//下文所说自身需要实现的第一个功能
    public FileSystemXmlApplicationContext(String configLocations[], boolean refresh, ApplicationContext parent)
        throws BeansException
    {
        super(parent);
        setConfigLocations(configLocations);
        if(refresh)
            refresh();
    }
//下文所说自身需要实现的第二个功能
    protected Resource getResourceByPath(String path)
    {
        if(path != null && path.startsWith("/"))
            path = path.substring(1);
        return new FileSystemResource(path);
    }
}

在FileSystemXmlApplicationContext设计中,ApplicationContext应用上下文的功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext中实现了,在FileSystemXmlApplicationContext中,作为一个具体的应用上下文,只需实现和它自身相关的两个功能。

一个是:如果应用直接使用FileSystemXmlApplicationContext,需要实例化这个应用的上下文支持,同时启动IoC容器的refresh()过程。这个refresh()过程会牵涉IoC容器启动的一系列复杂操作,同时,对于不同容器的实现这些操作类似,因此在基类中将它封装好,需要时调用。

另一个:是与FileSystemXmlApplicationContext设计具体相关的功能,与怎样从文件系统中加载XML的Bean定义资源有关。不同的应用上下文实现对应着不同的读取BeanDefinition的方式,而FileSystemXmlApplicationContext通过这个过程,可以为在文件系统中读取以XML形式存在的BeanDefinition做准备。

IoC容器的初始化过程

Spring Ioc容器的初始化是由前面介绍的refresh()方法来启动的,这个方法标志着Ioc容器的正式启动。

包括三个步骤:BeanDefinition的Resource定位、载入、注册

编程的方式使用DefaultListableBeanFactory(XmlBeanFactory的基类)(IoC容器初始化的过程和以编程的方式类似,可以做参考):

//定义一个Resource来定位容器使用的BeanDefinition,这里使用的是ClassPathResource(类路径中找)
ClassPathResource res = new ClassPathResource("beans.xml");

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

//这里的Resource不能由DefaultListableBeanFactory直接使用,Spring通过使用BeanDefinitionReader对这些信息进行处理
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

reader.loadBeanDefinitions(res);

图2-1

在这里,我们可以看到使用ApplicationContext相对直接使用DefaultListableBeanFactory的好处,因为在ApplicationContext中,Spring已经为我们提供了一系列加载不同Resource的读取器的实现,而DefaultListableBeanFactory只是一个纯粹的IoC容器,需要为它配置特定的读取器才能完成这些功能。但是使用DefaultListableBeanFactory这种更底层的容器,能提高定制IoC容器的灵活性

BeanDefinition的Resource定位(这个定位过程类似容器寻找数据的过程):

回到ApplicationContext上来,例如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext以及XmlApplicationContext等。

102116_tfyO_3723612.png

FileSystemXmlApplicationContext的继承体系如上图2-2

FileSystemXmlApplicationContext通过继承AbstractApplicationContext具备了ResourceLoader读入以Resource定义的BeanDefinition的能力,因为AbstractApplicationContext的基类是DefaultResourceLoader,而DefaultResourceLoader实现了ResourceLoader接口

参照FileSystemXmlApplicationContext的代码清单,BeanDefinition资源定位(调用getResourceByPath)的过程,最初是由refresh来触发的,而这个refresh的调用是在FileSystemXmlApplicationContext构造函数中启动的。

转载于:https://my.oschina.net/u/3723612/blog/1614106

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值