Spring Ioc容器的设计:BeanFactory和ApplicationContext

Spring Ioc容器的设计java

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

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

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

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来使用)等code

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

构造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关系图:接口

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等。

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

FileSystemXmlApplicationContext经过继承AbstractApplicationContext具有了ResourceLoader读入以Resource定义的BeanDefinition的能力,由于AbstractApplicationContext的基类是DefaultResourceLoader,而DefaultResourceLoader实现了ResourceLoader接口

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

相关文章
相关标签/搜索